Merge branches 'x86/prototypes', 'x86/x2apic' and 'x86/debug' into x86/core
authorIngo Molnar <mingo@elte.hu>
Thu, 14 Aug 2008 12:58:22 +0000 (14:58 +0200)
committerIngo Molnar <mingo@elte.hu>
Thu, 14 Aug 2008 12:58:22 +0000 (14:58 +0200)
651 files changed:
Documentation/devices.txt
Documentation/ioctl-number.txt
Documentation/kernel-parameters.txt
Documentation/usb/auerswald.txt [deleted file]
Documentation/usb/power-management.txt
MAINTAINERS
arch/arm/mach-omap2/usb-tusb6010.c
arch/h8300/include/asm/Kbuild [moved from include/asm-h8300/Kbuild with 100% similarity]
arch/h8300/include/asm/a.out.h [moved from include/asm-h8300/a.out.h with 100% similarity]
arch/h8300/include/asm/atomic.h [moved from include/asm-h8300/atomic.h with 100% similarity]
arch/h8300/include/asm/auxvec.h [moved from include/asm-h8300/auxvec.h with 100% similarity]
arch/h8300/include/asm/bitops.h [moved from include/asm-h8300/bitops.h with 100% similarity]
arch/h8300/include/asm/bootinfo.h [moved from include/asm-h8300/bootinfo.h with 100% similarity]
arch/h8300/include/asm/bug.h [moved from include/asm-h8300/bug.h with 100% similarity]
arch/h8300/include/asm/bugs.h [moved from include/asm-h8300/bugs.h with 100% similarity]
arch/h8300/include/asm/byteorder.h [moved from include/asm-h8300/byteorder.h with 100% similarity]
arch/h8300/include/asm/cache.h [moved from include/asm-h8300/cache.h with 100% similarity]
arch/h8300/include/asm/cachectl.h [moved from include/asm-h8300/cachectl.h with 100% similarity]
arch/h8300/include/asm/cacheflush.h [moved from include/asm-h8300/cacheflush.h with 100% similarity]
arch/h8300/include/asm/checksum.h [moved from include/asm-h8300/checksum.h with 100% similarity]
arch/h8300/include/asm/cputime.h [moved from include/asm-h8300/cputime.h with 100% similarity]
arch/h8300/include/asm/current.h [moved from include/asm-h8300/current.h with 100% similarity]
arch/h8300/include/asm/dbg.h [moved from include/asm-h8300/dbg.h with 100% similarity]
arch/h8300/include/asm/delay.h [moved from include/asm-h8300/delay.h with 100% similarity]
arch/h8300/include/asm/device.h [moved from include/asm-h8300/device.h with 100% similarity]
arch/h8300/include/asm/div64.h [moved from include/asm-h8300/div64.h with 100% similarity]
arch/h8300/include/asm/dma.h [moved from include/asm-h8300/dma.h with 100% similarity]
arch/h8300/include/asm/elf.h [moved from include/asm-h8300/elf.h with 100% similarity]
arch/h8300/include/asm/emergency-restart.h [moved from include/asm-h8300/emergency-restart.h with 100% similarity]
arch/h8300/include/asm/errno.h [moved from include/asm-h8300/errno.h with 100% similarity]
arch/h8300/include/asm/fb.h [moved from include/asm-h8300/fb.h with 100% similarity]
arch/h8300/include/asm/fcntl.h [moved from include/asm-h8300/fcntl.h with 100% similarity]
arch/h8300/include/asm/flat.h [moved from include/asm-h8300/flat.h with 100% similarity]
arch/h8300/include/asm/fpu.h [moved from include/asm-h8300/fpu.h with 100% similarity]
arch/h8300/include/asm/futex.h [moved from include/asm-h8300/futex.h with 100% similarity]
arch/h8300/include/asm/gpio.h [moved from include/asm-h8300/gpio.h with 100% similarity]
arch/h8300/include/asm/hardirq.h [moved from include/asm-h8300/hardirq.h with 100% similarity]
arch/h8300/include/asm/hw_irq.h [moved from include/asm-h8300/hw_irq.h with 100% similarity]
arch/h8300/include/asm/io.h [moved from include/asm-h8300/io.h with 100% similarity]
arch/h8300/include/asm/ioctl.h [moved from include/asm-h8300/ioctl.h with 100% similarity]
arch/h8300/include/asm/ioctls.h [moved from include/asm-h8300/ioctls.h with 100% similarity]
arch/h8300/include/asm/ipcbuf.h [moved from include/asm-h8300/ipcbuf.h with 100% similarity]
arch/h8300/include/asm/irq.h [moved from include/asm-h8300/irq.h with 100% similarity]
arch/h8300/include/asm/irq_regs.h [moved from include/asm-h8300/irq_regs.h with 100% similarity]
arch/h8300/include/asm/kdebug.h [moved from include/asm-h8300/kdebug.h with 100% similarity]
arch/h8300/include/asm/kmap_types.h [moved from include/asm-h8300/kmap_types.h with 100% similarity]
arch/h8300/include/asm/linkage.h [moved from include/asm-h8300/linkage.h with 100% similarity]
arch/h8300/include/asm/local.h [moved from include/asm-h8300/local.h with 100% similarity]
arch/h8300/include/asm/mc146818rtc.h [moved from include/asm-h8300/mc146818rtc.h with 100% similarity]
arch/h8300/include/asm/md.h [moved from include/asm-h8300/md.h with 100% similarity]
arch/h8300/include/asm/mman.h [moved from include/asm-h8300/mman.h with 100% similarity]
arch/h8300/include/asm/mmu.h [moved from include/asm-h8300/mmu.h with 100% similarity]
arch/h8300/include/asm/mmu_context.h [moved from include/asm-h8300/mmu_context.h with 100% similarity]
arch/h8300/include/asm/module.h [moved from include/asm-h8300/module.h with 100% similarity]
arch/h8300/include/asm/msgbuf.h [moved from include/asm-h8300/msgbuf.h with 100% similarity]
arch/h8300/include/asm/mutex.h [moved from include/asm-h8300/mutex.h with 100% similarity]
arch/h8300/include/asm/page.h [moved from include/asm-h8300/page.h with 100% similarity]
arch/h8300/include/asm/page_offset.h [moved from include/asm-h8300/page_offset.h with 100% similarity]
arch/h8300/include/asm/param.h [moved from include/asm-h8300/param.h with 100% similarity]
arch/h8300/include/asm/pci.h [moved from include/asm-h8300/pci.h with 100% similarity]
arch/h8300/include/asm/percpu.h [moved from include/asm-h8300/percpu.h with 100% similarity]
arch/h8300/include/asm/pgalloc.h [moved from include/asm-h8300/pgalloc.h with 100% similarity]
arch/h8300/include/asm/pgtable.h [moved from include/asm-h8300/pgtable.h with 100% similarity]
arch/h8300/include/asm/poll.h [moved from include/asm-h8300/poll.h with 100% similarity]
arch/h8300/include/asm/posix_types.h [moved from include/asm-h8300/posix_types.h with 100% similarity]
arch/h8300/include/asm/processor.h [moved from include/asm-h8300/processor.h with 100% similarity]
arch/h8300/include/asm/ptrace.h [moved from include/asm-h8300/ptrace.h with 100% similarity]
arch/h8300/include/asm/regs267x.h [moved from include/asm-h8300/regs267x.h with 100% similarity]
arch/h8300/include/asm/regs306x.h [moved from include/asm-h8300/regs306x.h with 100% similarity]
arch/h8300/include/asm/resource.h [moved from include/asm-h8300/resource.h with 100% similarity]
arch/h8300/include/asm/scatterlist.h [moved from include/asm-h8300/scatterlist.h with 100% similarity]
arch/h8300/include/asm/sections.h [moved from include/asm-h8300/sections.h with 100% similarity]
arch/h8300/include/asm/segment.h [moved from include/asm-h8300/segment.h with 100% similarity]
arch/h8300/include/asm/sembuf.h [moved from include/asm-h8300/sembuf.h with 100% similarity]
arch/h8300/include/asm/setup.h [moved from include/asm-h8300/setup.h with 100% similarity]
arch/h8300/include/asm/sh_bios.h [moved from include/asm-h8300/sh_bios.h with 100% similarity]
arch/h8300/include/asm/shm.h [moved from include/asm-h8300/shm.h with 100% similarity]
arch/h8300/include/asm/shmbuf.h [moved from include/asm-h8300/shmbuf.h with 100% similarity]
arch/h8300/include/asm/shmparam.h [moved from include/asm-h8300/shmparam.h with 100% similarity]
arch/h8300/include/asm/sigcontext.h [moved from include/asm-h8300/sigcontext.h with 100% similarity]
arch/h8300/include/asm/siginfo.h [moved from include/asm-h8300/siginfo.h with 100% similarity]
arch/h8300/include/asm/signal.h [moved from include/asm-h8300/signal.h with 100% similarity]
arch/h8300/include/asm/smp.h [moved from include/asm-h8300/smp.h with 100% similarity]
arch/h8300/include/asm/socket.h [moved from include/asm-h8300/socket.h with 100% similarity]
arch/h8300/include/asm/sockios.h [moved from include/asm-h8300/sockios.h with 100% similarity]
arch/h8300/include/asm/spinlock.h [moved from include/asm-h8300/spinlock.h with 100% similarity]
arch/h8300/include/asm/stat.h [moved from include/asm-h8300/stat.h with 100% similarity]
arch/h8300/include/asm/statfs.h [moved from include/asm-h8300/statfs.h with 100% similarity]
arch/h8300/include/asm/string.h [moved from include/asm-h8300/string.h with 100% similarity]
arch/h8300/include/asm/system.h [moved from include/asm-h8300/system.h with 100% similarity]
arch/h8300/include/asm/target_time.h [moved from include/asm-h8300/target_time.h with 100% similarity]
arch/h8300/include/asm/termbits.h [moved from include/asm-h8300/termbits.h with 100% similarity]
arch/h8300/include/asm/termios.h [moved from include/asm-h8300/termios.h with 100% similarity]
arch/h8300/include/asm/thread_info.h [moved from include/asm-h8300/thread_info.h with 100% similarity]
arch/h8300/include/asm/timex.h [moved from include/asm-h8300/timex.h with 100% similarity]
arch/h8300/include/asm/tlb.h [moved from include/asm-h8300/tlb.h with 100% similarity]
arch/h8300/include/asm/tlbflush.h [moved from include/asm-h8300/tlbflush.h with 100% similarity]
arch/h8300/include/asm/topology.h [moved from include/asm-h8300/topology.h with 100% similarity]
arch/h8300/include/asm/traps.h [moved from include/asm-h8300/traps.h with 100% similarity]
arch/h8300/include/asm/types.h [moved from include/asm-h8300/types.h with 100% similarity]
arch/h8300/include/asm/uaccess.h [moved from include/asm-h8300/uaccess.h with 100% similarity]
arch/h8300/include/asm/ucontext.h [moved from include/asm-h8300/ucontext.h with 100% similarity]
arch/h8300/include/asm/unaligned.h [moved from include/asm-h8300/unaligned.h with 100% similarity]
arch/h8300/include/asm/unistd.h [moved from include/asm-h8300/unistd.h with 100% similarity]
arch/h8300/include/asm/user.h [moved from include/asm-h8300/user.h with 100% similarity]
arch/h8300/include/asm/virtconvert.h [moved from include/asm-h8300/virtconvert.h with 100% similarity]
arch/sparc/include/asm/irq_64.h
arch/sparc/include/asm/of_device.h
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/kstack.h [new file with mode: 0644]
arch/sparc64/kernel/process.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/stacktrace.c
arch/sparc64/kernel/traps.c
arch/sparc64/lib/mcount.S
arch/sparc64/mm/init.c
arch/sparc64/mm/ultra.S
arch/x86/Kconfig
arch/x86/boot/compressed/misc.c
arch/x86/es7000/Makefile [moved from arch/x86/mach-es7000/Makefile with 100% similarity]
arch/x86/es7000/es7000.h [moved from arch/x86/mach-es7000/es7000.h with 89% similarity]
arch/x86/es7000/es7000plat.c [moved from arch/x86/mach-es7000/es7000plat.c with 99% similarity]
arch/x86/kernel/Makefile
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apic_32.c
arch/x86/kernel/apic_64.c
arch/x86/kernel/asm-offsets_64.c
arch/x86/kernel/cpu/common_64.c
arch/x86/kernel/cpu/feature_names.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/genapic_64.c
arch/x86/kernel/genapic_flat_64.c
arch/x86/kernel/genx2apic_cluster.c [new file with mode: 0644]
arch/x86/kernel/genx2apic_phys.c [new file with mode: 0644]
arch/x86/kernel/genx2apic_uv_x.c
arch/x86/kernel/i8259.c
arch/x86/kernel/io_apic_32.c
arch/x86/kernel/io_apic_64.c
arch/x86/kernel/irqinit_32.c
arch/x86/kernel/mpparse.c
arch/x86/kernel/numaq_32.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/setup.c
arch/x86/kernel/setup_percpu.c
arch/x86/kernel/signal_64.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/summit_32.c
arch/x86/kernel/syscall_64.c
arch/x86/kernel/traps_64.c
arch/x86/kernel/vmi_32.c
arch/x86/lguest/boot.c
arch/x86/mach-default/setup.c
arch/x86/mach-generic/Makefile
arch/x86/mach-generic/bigsmp.c
arch/x86/mach-generic/es7000.c
arch/x86/mach-generic/numaq.c
arch/x86/mach-generic/summit.c
arch/x86/xen/enlighten.c
crypto/digest.c
crypto/tcrypt.c
drivers/Makefile
drivers/char/hw_random/via-rng.c
drivers/crypto/padlock-aes.c
drivers/crypto/padlock-sha.c
drivers/crypto/talitos.c
drivers/i2c/chips/isp1301_omap.c
drivers/input/serio/i8042-sparcio.h
drivers/net/bnx2x.h
drivers/net/bnx2x_fw_defs.h
drivers/net/bnx2x_hsi.h
drivers/net/bnx2x_init.h
drivers/net/bnx2x_init_values.h
drivers/net/bnx2x_link.c
drivers/net/bnx2x_link.h
drivers/net/bnx2x_main.c
drivers/net/bnx2x_reg.h
drivers/pci/Makefile
drivers/pci/dma_remapping.h [new file with mode: 0644]
drivers/pci/dmar.c
drivers/pci/intel-iommu.c
drivers/pci/intel-iommu.h
drivers/pci/intr_remapping.c [new file with mode: 0644]
drivers/pci/intr_remapping.h [new file with mode: 0644]
drivers/sbus/sbus.c
drivers/serial/sunhv.c
drivers/serial/sunsab.c
drivers/serial/sunsu.c
drivers/serial/sunzilog.c
drivers/usb/Kconfig
drivers/usb/atm/cxacru.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.h
drivers/usb/core/driver.c
drivers/usb/core/message.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/f_acm.c
drivers/usb/gadget/f_ecm.c
drivers/usb/gadget/f_rndis.c
drivers/usb/gadget/f_serial.c
drivers/usb/gadget/f_subset.c
drivers/usb/gadget/gadget_chips.h
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/u_serial.c
drivers/usb/gadget/u_serial.h
drivers/usb/host/isp1760-hcd.c
drivers/usb/host/isp1760-hcd.h
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-q.c
drivers/usb/host/ohci.h
drivers/usb/host/r8a66597-hcd.c
drivers/usb/misc/Kconfig
drivers/usb/misc/Makefile
drivers/usb/misc/auerswald.c [deleted file]
drivers/usb/musb/Kconfig [new file with mode: 0644]
drivers/usb/musb/Makefile [new file with mode: 0644]
drivers/usb/musb/cppi_dma.c [new file with mode: 0644]
drivers/usb/musb/cppi_dma.h [new file with mode: 0644]
drivers/usb/musb/davinci.c [new file with mode: 0644]
drivers/usb/musb/davinci.h [new file with mode: 0644]
drivers/usb/musb/musb_core.c [new file with mode: 0644]
drivers/usb/musb/musb_core.h [new file with mode: 0644]
drivers/usb/musb/musb_debug.h [new file with mode: 0644]
drivers/usb/musb/musb_dma.h [new file with mode: 0644]
drivers/usb/musb/musb_gadget.c [new file with mode: 0644]
drivers/usb/musb/musb_gadget.h [new file with mode: 0644]
drivers/usb/musb/musb_gadget_ep0.c [new file with mode: 0644]
drivers/usb/musb/musb_host.c [new file with mode: 0644]
drivers/usb/musb/musb_host.h [new file with mode: 0644]
drivers/usb/musb/musb_io.h [new file with mode: 0644]
drivers/usb/musb/musb_procfs.c [new file with mode: 0644]
drivers/usb/musb/musb_regs.h [new file with mode: 0644]
drivers/usb/musb/musb_virthub.c [new file with mode: 0644]
drivers/usb/musb/musbhsdma.c [new file with mode: 0644]
drivers/usb/musb/omap2430.c [new file with mode: 0644]
drivers/usb/musb/omap2430.h [new file with mode: 0644]
drivers/usb/musb/tusb6010.c [new file with mode: 0644]
drivers/usb/musb/tusb6010.h [new file with mode: 0644]
drivers/usb/musb/tusb6010_omap.c [new file with mode: 0644]
drivers/usb/serial/Kconfig
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/sierra.c
drivers/usb/serial/usb-serial.c
drivers/usb/storage/Kconfig
drivers/usb/storage/Makefile
drivers/usb/storage/sierra_ms.c [new file with mode: 0644]
drivers/usb/storage/sierra_ms.h [new file with mode: 0644]
drivers/usb/storage/transport.c
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/usb.c
fs/dlm/config.c
fs/dlm/user.c
fs/xfs/linux-2.6/sema.h [deleted file]
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_buf.h
fs/xfs/linux-2.6/xfs_export.c
fs/xfs/linux-2.6/xfs_fs_subr.c
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_iops.h
fs/xfs/linux-2.6/xfs_linux.h
fs/xfs/linux-2.6/xfs_lrw.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_super.h
fs/xfs/linux-2.6/xfs_vnode.c
fs/xfs/linux-2.6/xfs_vnode.h
fs/xfs/quota/xfs_dquot.c
fs/xfs/quota/xfs_dquot.h
fs/xfs/quota/xfs_dquot_item.c
fs/xfs/quota/xfs_qm.c
fs/xfs/quota/xfs_qm.h
fs/xfs/quota/xfs_qm_bhv.c
fs/xfs/quota/xfs_qm_syscalls.c
fs/xfs/xfs_acl.c
fs/xfs/xfs_acl.h
fs/xfs/xfs_arch.h
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr.h
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_attr_leaf.h
fs/xfs/xfs_bit.c
fs/xfs/xfs_bit.h
fs/xfs/xfs_bmap.c
fs/xfs/xfs_btree.c
fs/xfs/xfs_btree.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_error.c
fs/xfs/xfs_error.h
fs/xfs/xfs_filestream.c
fs/xfs/xfs_ialloc_btree.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_itable.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log.h
fs/xfs/xfs_log_priv.h
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_rw.c
fs/xfs/xfs_trans.c
fs/xfs/xfs_trans.h
fs/xfs/xfs_trans_buf.c
fs/xfs/xfs_trans_item.c
fs/xfs/xfs_utils.c
fs/xfs/xfs_utils.h
fs/xfs/xfs_vfsops.c
fs/xfs/xfs_vnodeops.c
include/asm-x86/a.out-core.h
include/asm-x86/a.out.h
include/asm-x86/acpi.h
include/asm-x86/agp.h
include/asm-x86/alternative.h
include/asm-x86/amd_iommu.h
include/asm-x86/amd_iommu_types.h
include/asm-x86/apic.h
include/asm-x86/apicdef.h
include/asm-x86/arch_hooks.h
include/asm-x86/asm.h
include/asm-x86/atomic_32.h
include/asm-x86/atomic_64.h
include/asm-x86/auxvec.h
include/asm-x86/bigsmp/apic.h [moved from include/asm-x86/mach-bigsmp/mach_apic.h with 98% similarity]
include/asm-x86/bigsmp/apicdef.h [moved from include/asm-x86/mach-bigsmp/mach_apicdef.h with 74% similarity]
include/asm-x86/bigsmp/ipi.h [moved from include/asm-x86/mach-bigsmp/mach_ipi.h with 100% similarity]
include/asm-x86/bios_ebda.h
include/asm-x86/bitops.h
include/asm-x86/boot.h
include/asm-x86/bootparam.h
include/asm-x86/bug.h
include/asm-x86/bugs.h
include/asm-x86/byteorder.h
include/asm-x86/cache.h
include/asm-x86/cacheflush.h
include/asm-x86/calgary.h
include/asm-x86/checksum_32.h
include/asm-x86/checksum_64.h
include/asm-x86/cmpxchg_32.h
include/asm-x86/cmpxchg_64.h
include/asm-x86/compat.h
include/asm-x86/cpu.h
include/asm-x86/cpufeature.h
include/asm-x86/current.h
include/asm-x86/debugreg.h
include/asm-x86/delay.h
include/asm-x86/desc.h
include/asm-x86/desc_defs.h
include/asm-x86/device.h
include/asm-x86/div64.h
include/asm-x86/dma-mapping.h
include/asm-x86/dma.h
include/asm-x86/dmi.h
include/asm-x86/ds.h
include/asm-x86/dwarf2.h
include/asm-x86/e820.h
include/asm-x86/edac.h
include/asm-x86/efi.h
include/asm-x86/elf.h
include/asm-x86/emergency-restart.h
include/asm-x86/es7000/apic.h [moved from include/asm-x86/mach-es7000/mach_apic.h with 92% similarity]
include/asm-x86/es7000/apicdef.h [new file with mode: 0644]
include/asm-x86/es7000/ipi.h [moved from include/asm-x86/mach-es7000/mach_ipi.h with 83% similarity]
include/asm-x86/es7000/mpparse.h [moved from include/asm-x86/mach-es7000/mach_mpparse.h with 91% similarity]
include/asm-x86/es7000/wakecpu.h [moved from include/asm-x86/mach-es7000/mach_wakecpu.h with 95% similarity]
include/asm-x86/fb.h
include/asm-x86/fixmap.h
include/asm-x86/fixmap_32.h
include/asm-x86/fixmap_64.h
include/asm-x86/floppy.h
include/asm-x86/ftrace.h
include/asm-x86/futex.h
include/asm-x86/gart.h
include/asm-x86/genapic_32.h
include/asm-x86/genapic_64.h
include/asm-x86/geode.h
include/asm-x86/gpio.h
include/asm-x86/hardirq_32.h
include/asm-x86/hardirq_64.h
include/asm-x86/highmem.h
include/asm-x86/hpet.h
include/asm-x86/hugetlb.h
include/asm-x86/hw_irq.h
include/asm-x86/hypertransport.h
include/asm-x86/i387.h
include/asm-x86/i8253.h
include/asm-x86/i8259.h
include/asm-x86/ia32.h
include/asm-x86/ia32_unistd.h
include/asm-x86/idle.h
include/asm-x86/intel_arch_perfmon.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/ioctls.h
include/asm-x86/iommu.h
include/asm-x86/ipcbuf.h
include/asm-x86/ipi.h
include/asm-x86/irq.h
include/asm-x86/irq_regs_32.h
include/asm-x86/irq_remapping.h [new file with mode: 0644]
include/asm-x86/irq_vectors.h
include/asm-x86/ist.h
include/asm-x86/k8.h
include/asm-x86/kdebug.h
include/asm-x86/kexec.h
include/asm-x86/kgdb.h
include/asm-x86/kmap_types.h
include/asm-x86/kprobes.h
include/asm-x86/kvm.h
include/asm-x86/kvm_host.h
include/asm-x86/kvm_para.h
include/asm-x86/kvm_x86_emulate.h
include/asm-x86/ldt.h
include/asm-x86/lguest.h
include/asm-x86/lguest_hcall.h
include/asm-x86/linkage.h
include/asm-x86/local.h
include/asm-x86/mach-default/apm.h
include/asm-x86/mach-default/mach_apic.h
include/asm-x86/mach-default/mach_apicdef.h
include/asm-x86/mach-default/mach_ipi.h
include/asm-x86/mach-default/mach_mpparse.h
include/asm-x86/mach-default/mach_mpspec.h
include/asm-x86/mach-default/mach_timer.h
include/asm-x86/mach-default/mach_traps.h
include/asm-x86/mach-default/mach_wakecpu.h
include/asm-x86/mach-es7000/mach_apicdef.h [deleted file]
include/asm-x86/mach-generic/gpio.h
include/asm-x86/mach-generic/irq_vectors_limits.h
include/asm-x86/mach-generic/mach_apic.h
include/asm-x86/mach-generic/mach_apicdef.h
include/asm-x86/mach-generic/mach_ipi.h
include/asm-x86/mach-generic/mach_mpparse.h
include/asm-x86/mach-generic/mach_mpspec.h
include/asm-x86/mach-rdc321x/gpio.h
include/asm-x86/mach-summit/mach_apicdef.h [deleted file]
include/asm-x86/math_emu.h
include/asm-x86/mc146818rtc.h
include/asm-x86/mca.h
include/asm-x86/mca_dma.h
include/asm-x86/mce.h
include/asm-x86/mman.h
include/asm-x86/mmconfig.h
include/asm-x86/mmu.h
include/asm-x86/mmu_context.h
include/asm-x86/mmu_context_32.h
include/asm-x86/mmu_context_64.h
include/asm-x86/mmx.h
include/asm-x86/mmzone_32.h
include/asm-x86/mmzone_64.h
include/asm-x86/module.h
include/asm-x86/mpspec.h
include/asm-x86/mpspec_def.h
include/asm-x86/msgbuf.h
include/asm-x86/msidef.h
include/asm-x86/msr-index.h
include/asm-x86/msr.h
include/asm-x86/mtrr.h
include/asm-x86/mutex_32.h
include/asm-x86/mutex_64.h
include/asm-x86/nmi.h
include/asm-x86/nops.h
include/asm-x86/numa_32.h
include/asm-x86/numa_64.h
include/asm-x86/numaq.h
include/asm-x86/numaq/apic.h [moved from include/asm-x86/mach-numaq/mach_apic.h with 97% similarity]
include/asm-x86/numaq/apicdef.h [moved from include/asm-x86/mach-numaq/mach_apicdef.h with 75% similarity]
include/asm-x86/numaq/ipi.h [moved from include/asm-x86/mach-numaq/mach_ipi.h with 83% similarity]
include/asm-x86/numaq/mpparse.h [moved from include/asm-x86/mach-numaq/mach_mpparse.h with 50% similarity]
include/asm-x86/numaq/wakecpu.h [moved from include/asm-x86/mach-numaq/mach_wakecpu.h with 91% similarity]
include/asm-x86/olpc.h
include/asm-x86/page.h
include/asm-x86/page_32.h
include/asm-x86/page_64.h
include/asm-x86/param.h
include/asm-x86/paravirt.h
include/asm-x86/parport.h
include/asm-x86/pat.h
include/asm-x86/pci-direct.h
include/asm-x86/pci.h
include/asm-x86/pci_32.h
include/asm-x86/pci_64.h
include/asm-x86/pda.h
include/asm-x86/percpu.h
include/asm-x86/pgalloc.h
include/asm-x86/pgtable-2level-defs.h
include/asm-x86/pgtable-2level.h
include/asm-x86/pgtable-3level-defs.h
include/asm-x86/pgtable-3level.h
include/asm-x86/pgtable.h
include/asm-x86/pgtable_32.h
include/asm-x86/pgtable_64.h
include/asm-x86/posix_types_32.h
include/asm-x86/posix_types_64.h
include/asm-x86/prctl.h
include/asm-x86/processor-flags.h
include/asm-x86/processor.h
include/asm-x86/proto.h
include/asm-x86/ptrace-abi.h
include/asm-x86/ptrace.h
include/asm-x86/pvclock-abi.h
include/asm-x86/pvclock.h
include/asm-x86/reboot.h
include/asm-x86/reboot_fixups.h
include/asm-x86/required-features.h
include/asm-x86/resume-trace.h
include/asm-x86/rio.h
include/asm-x86/rwlock.h
include/asm-x86/rwsem.h
include/asm-x86/scatterlist.h
include/asm-x86/seccomp_32.h
include/asm-x86/seccomp_64.h
include/asm-x86/segment.h
include/asm-x86/sembuf.h
include/asm-x86/serial.h
include/asm-x86/setup.h
include/asm-x86/shmbuf.h
include/asm-x86/shmparam.h
include/asm-x86/sigcontext.h
include/asm-x86/sigcontext32.h
include/asm-x86/siginfo.h
include/asm-x86/signal.h
include/asm-x86/smp.h
include/asm-x86/socket.h
include/asm-x86/sockios.h
include/asm-x86/sparsemem.h
include/asm-x86/spinlock.h
include/asm-x86/spinlock_types.h
include/asm-x86/srat.h
include/asm-x86/stacktrace.h
include/asm-x86/stat.h
include/asm-x86/statfs.h
include/asm-x86/string_32.h
include/asm-x86/string_64.h
include/asm-x86/summit/apic.h [moved from include/asm-x86/mach-summit/mach_apic.h with 94% similarity]
include/asm-x86/summit/apicdef.h [new file with mode: 0644]
include/asm-x86/summit/ipi.h [moved from include/asm-x86/mach-summit/mach_ipi.h with 83% similarity]
include/asm-x86/summit/irq_vectors_limits.h [moved from include/asm-x86/mach-summit/irq_vectors_limits.h with 100% similarity]
include/asm-x86/summit/mpparse.h [moved from include/asm-x86/mach-summit/mach_mpparse.h with 96% similarity]
include/asm-x86/suspend_32.h
include/asm-x86/suspend_64.h
include/asm-x86/swiotlb.h
include/asm-x86/sync_bitops.h
include/asm-x86/system.h
include/asm-x86/system_64.h
include/asm-x86/tce.h
include/asm-x86/termbits.h
include/asm-x86/termios.h
include/asm-x86/therm_throt.h
include/asm-x86/thread_info.h
include/asm-x86/time.h
include/asm-x86/timer.h
include/asm-x86/timex.h
include/asm-x86/tlb.h
include/asm-x86/tlbflush.h
include/asm-x86/topology.h
include/asm-x86/trampoline.h
include/asm-x86/traps.h
include/asm-x86/tsc.h
include/asm-x86/types.h
include/asm-x86/uaccess.h
include/asm-x86/uaccess_32.h
include/asm-x86/uaccess_64.h
include/asm-x86/ucontext.h
include/asm-x86/unaligned.h
include/asm-x86/unistd_32.h
include/asm-x86/unistd_64.h
include/asm-x86/unwind.h
include/asm-x86/user32.h
include/asm-x86/user_32.h
include/asm-x86/user_64.h
include/asm-x86/uv/bios.h
include/asm-x86/uv/uv_bau.h
include/asm-x86/uv/uv_hub.h
include/asm-x86/uv/uv_mmrs.h
include/asm-x86/vdso.h
include/asm-x86/vga.h
include/asm-x86/vgtod.h
include/asm-x86/visws/cobalt.h
include/asm-x86/visws/lithium.h
include/asm-x86/visws/piix4.h
include/asm-x86/vm86.h
include/asm-x86/vmi_time.h
include/asm-x86/vsyscall.h
include/asm-x86/xen/events.h
include/asm-x86/xen/grant_table.h
include/asm-x86/xen/hypercall.h
include/asm-x86/xen/hypervisor.h
include/asm-x86/xen/interface.h
include/asm-x86/xen/interface_32.h
include/asm-x86/xen/interface_64.h
include/asm-x86/xen/page.h
include/crypto/hash.h
include/linux/completion.h
include/linux/cred.h [new file with mode: 0644]
include/linux/dmar.h
include/linux/irq.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/usb.h
include/linux/usb/musb.h [new file with mode: 0644]
include/linux/usb/serial.h
include/net/ip6_route.h
include/net/ip_vs.h
include/net/pkt_sched.h
kernel/irq/manage.c
net/core/gen_estimator.c
net/core/pktgen.c
net/dccp/proto.c
net/ipv4/igmp.c
net/ipv4/ipvs/ip_vs_app.c
net/ipv4/ipvs/ip_vs_conn.c
net/ipv4/ipvs/ip_vs_ctl.c
net/ipv4/ipvs/ip_vs_dh.c
net/ipv4/ipvs/ip_vs_est.c
net/ipv4/ipvs/ip_vs_lblc.c
net/ipv4/ipvs/ip_vs_lblcr.c
net/ipv4/ipvs/ip_vs_lc.c
net/ipv4/ipvs/ip_vs_nq.c
net/ipv4/ipvs/ip_vs_proto.c
net/ipv4/ipvs/ip_vs_rr.c
net/ipv4/ipvs/ip_vs_sched.c
net/ipv4/ipvs/ip_vs_sed.c
net/ipv4/ipvs/ip_vs_sh.c
net/ipv4/ipvs/ip_vs_sync.c
net/ipv4/ipvs/ip_vs_wlc.c
net/ipv4/ipvs/ip_vs_wrr.c
net/ipv4/udp.c
net/ipv6/route.c
net/ipv6/udp.c
net/rxrpc/ar-accept.c
net/sched/act_api.c
net/sched/sch_api.c
net/sched/sch_generic.c
net/sched/sch_htb.c
net/tipc/subscr.c
net/wireless/wext.c
net/xfrm/xfrm_output.c

index e6244cde26e9406527dfcaa9aae9edf9e17c6161..05c80645e4ee172fafa118eea8f8b56aec242209 100644 (file)
@@ -2560,9 +2560,6 @@ Your cooperation is appreciated.
                 96 = /dev/usb/hiddev0  1st USB HID device
                    ...
                111 = /dev/usb/hiddev15 16th USB HID device
-               112 = /dev/usb/auer0    1st auerswald ISDN device
-                   ...
-               127 = /dev/usb/auer15   16th auerswald ISDN device
                128 = /dev/usb/brlvgr0  First Braille Voyager device
                    ...
                131 = /dev/usb/brlvgr3  Fourth Braille Voyager device
index 3bb5f466a90db3e971b42fb26c60d716a30878ed..1c6b545635a27741abe8f3b5bb10490416bce0fa 100644 (file)
@@ -105,7 +105,6 @@ Code        Seq#    Include File            Comments
 'T'    all     linux/soundcard.h       conflict!
 'T'    all     asm-i386/ioctls.h       conflict!
 'U'    00-EF   linux/drivers/usb/usb.h
-'U'    F0-FF   drivers/usb/auerswald.c
 'V'    all     linux/vt.h
 'W'    00-1F   linux/watchdog.h        conflict!
 'W'    00-1F   linux/wanrouter.h       conflict!
index e7bea3e853044e54f3ee863ad3d295b0df84a522..0f130a4f9ba3195ab21305a656df222990599c61 100644 (file)
@@ -1420,6 +1420,12 @@ and is between 256 and 4096 characters. It is defined in the file
 
        nolapic_timer   [X86-32,APIC] Do not use the local APIC timer.
 
+       nox2apic        [X86-64,APIC] Do not enable x2APIC mode.
+
+       x2apic_phys     [X86-64,APIC] Use x2apic physical mode instead of
+                       default x2apic cluster mode on platforms
+                       supporting x2apic.
+
        noltlbs         [PPC] Do not use large page/tlb entries for kernel
                        lowmem mapping on PPC40x.
 
diff --git a/Documentation/usb/auerswald.txt b/Documentation/usb/auerswald.txt
deleted file mode 100644 (file)
index 7ee4d8f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-               Auerswald USB kernel driver
-               ===========================
-
-What is it? What can I do with it?
-==================================
-The auerswald USB kernel driver connects your linux 2.4.x
-system to the auerswald usb-enabled devices.
-
-There are two types of auerswald usb devices:
-a) small PBX systems (ISDN)
-b) COMfort system telephones (ISDN)
-
-The driver installation creates the devices
-/dev/usb/auer0..15. These devices carry a vendor-
-specific protocol. You may run all auerswald java
-software on it. The java software needs a native
-library "libAuerUsbJNINative.so" installed on
-your system. This library is available from
-auerswald and shipped as part of the java software.
-
-You may create the devices with:
-       mknod -m 666 /dev/usb/auer0 c 180 112
-       ...
-       mknod -m 666 /dev/usb/auer15 c 180 127
-
-Future plans
-============
-- Connection to ISDN4LINUX (the hisax interface)
-
-The maintainer of this driver is wolfgang@iksw-muees.de
index b2fc4d4a99177be7bd48dce560d1f28417c60aa9..9d31140e3f5bc2db17e446b426a4ecfacbbf99fc 100644 (file)
@@ -436,7 +436,12 @@ post_reset; the USB core guarantees that this is true of internal
 suspend/resume events as well.
 
 If a driver wants to block all suspend/resume calls during some
-critical section, it can simply acquire udev->pm_mutex.
+critical section, it can simply acquire udev->pm_mutex. Note that
+calls to resume may be triggered indirectly. Block IO due to memory
+allocations can make the vm subsystem resume a device. Thus while
+holding this lock you must not allocate memory with GFP_KERNEL or
+GFP_NOFS.
+
 Alternatively, if the critical section might call some of the
 usb_autopm_* routines, the driver can avoid deadlock by doing:
 
index af6aa4e4b39264313d8b2fa0dc59820877ab2600..4c5e9fe0f7db5cd80b3fe2c4a76d38a3df1d7fcc 100644 (file)
@@ -2928,6 +2928,12 @@ M:       jirislaby@gmail.com
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
+MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
+P:     Felipe Balbi
+M:     felipe.balbi@nokia.com
+L:     linux-usb@vger.kernel.org
+S:     Maintained
+
 MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
 P:     Andrew Gallatin
 M:     gallatin@myri.com
@@ -3076,6 +3082,7 @@ M:        horms@verge.net.au
 P:     Julian Anastasov
 M:     ja@ssi.bg
 L:     netdev@vger.kernel.org
+L:     lvs-devel@vger.kernel.org
 S:     Maintained
 
 NFS, SUNRPC, AND LOCKD CLIENTS
@@ -4195,12 +4202,6 @@ M:       oliver@neukum.name
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 
-USB AUERSWALD DRIVER
-P:     Wolfgang Muees
-M:     wolfgang@iksw-muees.de
-L:      linux-usb@vger.kernel.org
-S:     Maintained
-
 USB BLOCK DRIVER (UB ub)
 P:     Pete Zaitcev
 M:     zaitcev@redhat.com
index 1607c941d95fd0848d12eaf202b17a794066f25c..10ef464d6be7f3f2768a1a7d95d6adb68e88ed17 100644 (file)
@@ -317,7 +317,6 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
                printk(error, 6, status);
                return -ENODEV;
        }
-       data->multipoint = 1;
        tusb_device.dev.platform_data = data;
 
        /* REVISIT let the driver know what DMA channels work */
index 3473e25231d96e3fe63a0227cf3103d409074cf4..e3dd9303643dd8f161fd5fd5234abac5a5b77a31 100644 (file)
@@ -93,4 +93,8 @@ static inline unsigned long get_softint(void)
 void __trigger_all_cpu_backtrace(void);
 #define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
 
+extern void *hardirq_stack[NR_CPUS];
+extern void *softirq_stack[NR_CPUS];
+#define __ARCH_HAS_DO_SOFTIRQ
+
 #endif
index e5f5aedc2293e6b857ef0f5753050aa5c733bb91..bba777a416d3bf31b7ab4b5bb5a393ea7cc2c9f7 100644 (file)
@@ -30,8 +30,7 @@ struct of_device
 extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name);
 extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size);
 
-/* These are just here during the transition */
-#include <linux/of_device.h>
+/* This is just here during the transition */
 #include <linux/of_platform.h>
 
 #endif /* __KERNEL__ */
index ba43d85e8dded537cfeb4a23c510456e4f2c956f..9b6689d9d57097239641d51653dc921e2607b997 100644 (file)
@@ -682,10 +682,32 @@ void ack_bad_irq(unsigned int virt_irq)
               ino, virt_irq);
 }
 
+void *hardirq_stack[NR_CPUS];
+void *softirq_stack[NR_CPUS];
+
+static __attribute__((always_inline)) void *set_hardirq_stack(void)
+{
+       void *orig_sp, *sp = hardirq_stack[smp_processor_id()];
+
+       __asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp));
+       if (orig_sp < sp ||
+           orig_sp > (sp + THREAD_SIZE)) {
+               sp += THREAD_SIZE - 192 - STACK_BIAS;
+               __asm__ __volatile__("mov %0, %%sp" : : "r" (sp));
+       }
+
+       return orig_sp;
+}
+static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp)
+{
+       __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp));
+}
+
 void handler_irq(int irq, struct pt_regs *regs)
 {
        unsigned long pstate, bucket_pa;
        struct pt_regs *old_regs;
+       void *orig_sp;
 
        clear_softint(1 << irq);
 
@@ -703,6 +725,8 @@ void handler_irq(int irq, struct pt_regs *regs)
                               "i" (PSTATE_IE)
                             : "memory");
 
+       orig_sp = set_hardirq_stack();
+
        while (bucket_pa) {
                struct irq_desc *desc;
                unsigned long next_pa;
@@ -719,10 +743,38 @@ void handler_irq(int irq, struct pt_regs *regs)
                bucket_pa = next_pa;
        }
 
+       restore_hardirq_stack(orig_sp);
+
        irq_exit();
        set_irq_regs(old_regs);
 }
 
+void do_softirq(void)
+{
+       unsigned long flags;
+
+       if (in_interrupt())
+               return;
+
+       local_irq_save(flags);
+
+       if (local_softirq_pending()) {
+               void *orig_sp, *sp = softirq_stack[smp_processor_id()];
+
+               sp += THREAD_SIZE - 192 - STACK_BIAS;
+
+               __asm__ __volatile__("mov %%sp, %0\n\t"
+                                    "mov %1, %%sp"
+                                    : "=&r" (orig_sp)
+                                    : "r" (sp));
+               __do_softirq();
+               __asm__ __volatile__("mov %0, %%sp"
+                                    : : "r" (orig_sp));
+       }
+
+       local_irq_restore(flags);
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 void fixup_irqs(void)
 {
diff --git a/arch/sparc64/kernel/kstack.h b/arch/sparc64/kernel/kstack.h
new file mode 100644 (file)
index 0000000..4248d96
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef _KSTACK_H
+#define _KSTACK_H
+
+#include <linux/thread_info.h>
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+#include <asm/irq.h>
+
+/* SP must be STACK_BIAS adjusted already.  */
+static inline bool kstack_valid(struct thread_info *tp, unsigned long sp)
+{
+       unsigned long base = (unsigned long) tp;
+
+       if (sp >= (base + sizeof(struct thread_info)) &&
+           sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
+               return true;
+
+       if (hardirq_stack[tp->cpu]) {
+               base = (unsigned long) hardirq_stack[tp->cpu];
+               if (sp >= base &&
+                   sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
+                       return true;
+               base = (unsigned long) softirq_stack[tp->cpu];
+               if (sp >= base &&
+                   sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
+                       return true;
+       }
+       return false;
+}
+
+/* Does "regs" point to a valid pt_regs trap frame?  */
+static inline bool kstack_is_trap_frame(struct thread_info *tp, struct pt_regs *regs)
+{
+       unsigned long base = (unsigned long) tp;
+       unsigned long addr = (unsigned long) regs;
+
+       if (addr >= base &&
+           addr <= (base + THREAD_SIZE - sizeof(*regs)))
+               goto check_magic;
+
+       if (hardirq_stack[tp->cpu]) {
+               base = (unsigned long) hardirq_stack[tp->cpu];
+               if (addr >= base &&
+                   addr <= (base + THREAD_SIZE - sizeof(*regs)))
+                       goto check_magic;
+               base = (unsigned long) softirq_stack[tp->cpu];
+               if (addr >= base &&
+                   addr <= (base + THREAD_SIZE - sizeof(*regs)))
+                       goto check_magic;
+       }
+       return false;
+
+check_magic:
+       if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC)
+               return true;
+       return false;
+
+}
+
+#endif /* _KSTACK_H */
index 7f5debdc5fed6ad2a4ae86b1ff78836efe8dce03..15f4178592e762d4bbff775679ae80c70e91423d 100644 (file)
@@ -52,6 +52,8 @@
 #include <asm/irq_regs.h>
 #include <asm/smp.h>
 
+#include "kstack.h"
+
 static void sparc64_yield(int cpu)
 {
        if (tlb_type != hypervisor)
@@ -235,19 +237,6 @@ void show_regs(struct pt_regs *regs)
 struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
 static DEFINE_SPINLOCK(global_reg_snapshot_lock);
 
-static bool kstack_valid(struct thread_info *tp, struct reg_window *rw)
-{
-       unsigned long thread_base, fp;
-
-       thread_base = (unsigned long) tp;
-       fp = (unsigned long) rw;
-
-       if (fp < (thread_base + sizeof(struct thread_info)) ||
-           fp >= (thread_base + THREAD_SIZE))
-               return false;
-       return true;
-}
-
 static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
                              int this_cpu)
 {
@@ -264,11 +253,11 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
 
                rw = (struct reg_window *)
                        (regs->u_regs[UREG_FP] + STACK_BIAS);
-               if (kstack_valid(tp, rw)) {
+               if (kstack_valid(tp, (unsigned long) rw)) {
                        global_reg_snapshot[this_cpu].i7 = rw->ins[7];
                        rw = (struct reg_window *)
                                (rw->ins[6] + STACK_BIAS);
-                       if (kstack_valid(tp, rw))
+                       if (kstack_valid(tp, (unsigned long) rw))
                                global_reg_snapshot[this_cpu].rpc = rw->ins[7];
                }
        } else {
@@ -828,7 +817,7 @@ out:
 unsigned long get_wchan(struct task_struct *task)
 {
        unsigned long pc, fp, bias = 0;
-       unsigned long thread_info_base;
+       struct thread_info *tp;
        struct reg_window *rw;
         unsigned long ret = 0;
        int count = 0; 
@@ -837,14 +826,12 @@ unsigned long get_wchan(struct task_struct *task)
             task->state == TASK_RUNNING)
                goto out;
 
-       thread_info_base = (unsigned long) task_stack_page(task);
+       tp = task_thread_info(task);
        bias = STACK_BIAS;
        fp = task_thread_info(task)->ksp + bias;
 
        do {
-               /* Bogus frame pointer? */
-               if (fp < (thread_info_base + sizeof(struct thread_info)) ||
-                   fp >= (thread_info_base + THREAD_SIZE))
+               if (!kstack_valid(tp, fp))
                        break;
                rw = (struct reg_window *) fp;
                pc = rw->ins[7];
index 27b81775a4decd16c43f32df32c8347407d82bb4..743ccad61c60921b36c9bf42a556dac79ac4e23c 100644 (file)
@@ -858,9 +858,7 @@ void smp_tsb_sync(struct mm_struct *mm)
 extern unsigned long xcall_flush_tlb_mm;
 extern unsigned long xcall_flush_tlb_pending;
 extern unsigned long xcall_flush_tlb_kernel_range;
-#ifdef CONFIG_MAGIC_SYSRQ
 extern unsigned long xcall_fetch_glob_regs;
-#endif
 extern unsigned long xcall_receive_signal;
 extern unsigned long xcall_new_mmu_context_version;
 #ifdef CONFIG_KGDB
@@ -1005,12 +1003,10 @@ void kgdb_roundup_cpus(unsigned long flags)
 }
 #endif
 
-#ifdef CONFIG_MAGIC_SYSRQ
 void smp_fetch_global_regs(void)
 {
        smp_cross_call(&xcall_fetch_glob_regs, 0, 0, 0);
 }
-#endif
 
 /* We know that the window frames of the user have been flushed
  * to the stack before we get here because all callers of us
index e9d7f0660f2e044643182cb2e85f9fde7dc5006b..4e21d4a57d3b3f2ea536ed5707d61fbf6bc94181 100644 (file)
@@ -5,10 +5,12 @@
 #include <asm/ptrace.h>
 #include <asm/stacktrace.h>
 
+#include "kstack.h"
+
 void save_stack_trace(struct stack_trace *trace)
 {
-       unsigned long ksp, fp, thread_base;
        struct thread_info *tp = task_thread_info(current);
+       unsigned long ksp, fp;
 
        stack_trace_flush();
 
@@ -18,23 +20,18 @@ void save_stack_trace(struct stack_trace *trace)
        );
 
        fp = ksp + STACK_BIAS;
-       thread_base = (unsigned long) tp;
        do {
                struct sparc_stackf *sf;
                struct pt_regs *regs;
                unsigned long pc;
 
-               /* Bogus frame pointer? */
-               if (fp < (thread_base + sizeof(struct thread_info)) ||
-                   fp > (thread_base + THREAD_SIZE - sizeof(struct sparc_stackf)))
+               if (!kstack_valid(tp, fp))
                        break;
 
                sf = (struct sparc_stackf *) fp;
                regs = (struct pt_regs *) (sf + 1);
 
-               if (((unsigned long)regs <=
-                    (thread_base + THREAD_SIZE - sizeof(*regs))) &&
-                   (regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
+               if (kstack_is_trap_frame(tp, regs)) {
                        if (!(regs->tstate & TSTATE_PRIV))
                                break;
                        pc = regs->tpc;
index 404e8561e2d0cec8b6d52a38be95d360624b0be7..3d924121c7960dd5b577c291a9a2dd716a272b2d 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/prom.h>
 
 #include "entry.h"
+#include "kstack.h"
 
 /* When an irrecoverable trap occurs at tl > 0, the trap entry
  * code logs the trap state registers at every level in the trap
@@ -2115,14 +2116,12 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
                struct pt_regs *regs;
                unsigned long pc;
 
-               /* Bogus frame pointer? */
-               if (fp < (thread_base + sizeof(struct thread_info)) ||
-                   fp >= (thread_base + THREAD_SIZE))
+               if (!kstack_valid(tp, fp))
                        break;
                sf = (struct sparc_stackf *) fp;
                regs = (struct pt_regs *) (sf + 1);
 
-               if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
+               if (kstack_is_trap_frame(tp, regs)) {
                        if (!(regs->tstate & TSTATE_PRIV))
                                break;
                        pc = regs->tpc;
index 7735a7a60533fa225256ad0bd2d94a00be26033a..fad90ddb3a28f1aae9a6a44e849b7393bbf87ac3 100644 (file)
@@ -48,12 +48,45 @@ mcount:
        sub             %g3, STACK_BIAS, %g3
        cmp             %sp, %g3
        bg,pt           %xcc, 1f
-        sethi          %hi(panicstring), %g3
+        nop
+       lduh            [%g6 + TI_CPU], %g1
+       sethi           %hi(hardirq_stack), %g3
+       or              %g3, %lo(hardirq_stack), %g3
+       sllx            %g1, 3, %g1
+       ldx             [%g3 + %g1], %g7
+       sub             %g7, STACK_BIAS, %g7
+       cmp             %sp, %g7
+       bleu,pt         %xcc, 2f
+        sethi          %hi(THREAD_SIZE), %g3
+       add             %g7, %g3, %g7
+       cmp             %sp, %g7
+       blu,pn          %xcc, 1f
+2:      sethi          %hi(softirq_stack), %g3
+       or              %g3, %lo(softirq_stack), %g3
+       ldx             [%g3 + %g1], %g7
+       cmp             %sp, %g7
+       bleu,pt         %xcc, 2f
+        sethi          %hi(THREAD_SIZE), %g3
+       add             %g7, %g3, %g7
+       cmp             %sp, %g7
+       blu,pn          %xcc, 1f
+        nop
+       /* If we are already on ovstack, don't hop onto it
+        * again, we are already trying to output the stack overflow
+        * message.
+        */
        sethi           %hi(ovstack), %g7               ! cant move to panic stack fast enough
         or             %g7, %lo(ovstack), %g7
-       add             %g7, OVSTACKSIZE, %g7
+       add             %g7, OVSTACKSIZE, %g3
+       sub             %g3, STACK_BIAS + 192, %g3
        sub             %g7, STACK_BIAS, %g7
-       mov             %g7, %sp
+       cmp             %sp, %g7
+       blu,pn          %xcc, 2f
+        cmp            %sp, %g3
+       bleu,pn         %xcc, 1f
+        nop
+2:     mov             %g3, %sp
+       sethi           %hi(panicstring), %g3
        call            prom_printf
         or             %g3, %lo(panicstring), %o0
        call            prom_halt
index 4e821b3ecb039faa71991809c0d4139354ee2a8d..217de3ea29e842cff4c0eff6be2b82c5a13f25fe 100644 (file)
@@ -49,6 +49,7 @@
 #include <asm/sstate.h>
 #include <asm/mdesc.h>
 #include <asm/cpudata.h>
+#include <asm/irq.h>
 
 #define MAX_PHYS_ADDRESS       (1UL << 42UL)
 #define KPTE_BITMAP_CHUNK_SZ   (256UL * 1024UL * 1024UL)
@@ -1771,6 +1772,16 @@ void __init paging_init(void)
        if (tlb_type == hypervisor)
                sun4v_mdesc_init();
 
+       /* Once the OF device tree and MDESC have been setup, we know
+        * the list of possible cpus.  Therefore we can allocate the
+        * IRQ stacks.
+        */
+       for_each_possible_cpu(i) {
+               /* XXX Use node local allocations... XXX */
+               softirq_stack[i] = __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
+               hardirq_stack[i] = __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
+       }
+
        /* Setup bootmem... */
        last_valid_pfn = end_pfn = bootmem_init(phys_base);
 
index ff1dc44d363e1cd1349d1b5ad7e26dda18dd394c..86773e89dc1bbf29cf71831948e6d79b5d43188b 100644 (file)
@@ -480,7 +480,6 @@ xcall_sync_tick:
        b               rtrap_xcall
         ldx            [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
 
-#ifdef CONFIG_MAGIC_SYSRQ
        .globl          xcall_fetch_glob_regs
 xcall_fetch_glob_regs:
        sethi           %hi(global_reg_snapshot), %g1
@@ -511,7 +510,6 @@ xcall_fetch_glob_regs:
        membar          #StoreStore
        stx             %g3, [%g1 + GR_SNAP_THREAD]
        retry
-#endif /* CONFIG_MAGIC_SYSRQ */
 
 #ifdef DCACHE_ALIASING_POSSIBLE
        .align          32
index ac2fb0641a041e4a28055867140f458613673dc2..53ab36878736ab4c65bded4b22314256f2c54000 100644 (file)
@@ -1657,6 +1657,14 @@ config DMAR_FLOPPY_WA
         workaround will setup a 1:1 mapping for the first
         16M to make floppy (an ISA device) work.
 
+config INTR_REMAP
+       bool "Support for Interrupt Remapping (EXPERIMENTAL)"
+       depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
+       help
+        Supports Interrupt remapping for IO-APIC and MSI devices.
+        To use x2apic mode in the CPU's which support x2APIC enhancements or
+        to support platforms with CPU's having > 8 bit APIC ID, say Y.
+
 source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pci/Kconfig"
index 9fea737064798bfd10ab78cf729b14cfd8b87681..aaf5a2131efceca569d6de7f88556ad13a661b2c 100644 (file)
@@ -16,7 +16,7 @@
  */
 #undef CONFIG_PARAVIRT
 #ifdef CONFIG_X86_32
-#define _ASM_DESC_H_ 1
+#define ASM_X86__DESC_H 1
 #endif
 
 #ifdef CONFIG_X86_64
similarity index 89%
rename from arch/x86/mach-es7000/es7000.h
rename to arch/x86/es7000/es7000.h
index c8d5aa132fa078d9f21cd52d550432766f0e8aa6..4e62f6fa95b8999979e47c084320093b4ac4223d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Written by: Garry Forsgren, Unisys Corporation
  *             Natalie Protasevich, Unisys Corporation
- * This file contains the code to configure and interface 
+ * This file contains the code to configure and interface
  * with Unisys ES7000 series hardware system manager.
  *
  * Copyright (c) 2003 Unisys Corporation.  All Rights Reserved.
@@ -18,7 +18,7 @@
  * with this program; if not, write the Free Software Foundation, Inc., 59
  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * Contact information: Unisys Corporation, Township Line & Union Meeting 
+ * Contact information: Unisys Corporation, Township Line & Union Meeting
  * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or:
  *
  * http://www.unisys.com
@@ -41,7 +41,7 @@
 #define        MIP_VALID               0x0100000000000000ULL
 #define        MIP_PORT(VALUE) ((VALUE >> 32) & 0xffff)
 
-#define        MIP_RD_LO(VALUE)        (VALUE & 0xffffffff)   
+#define        MIP_RD_LO(VALUE)        (VALUE & 0xffffffff)
 
 struct mip_reg_info {
        unsigned long long mip_info;
@@ -51,11 +51,11 @@ struct mip_reg_info {
 };
 
 struct part_info {
-       unsigned char type;   
+       unsigned char type;
        unsigned char length;
        unsigned char part_id;
        unsigned char apic_mode;
-       unsigned long snum;    
+       unsigned long snum;
        char ptype[16];
        char sname[64];
        char pname[64];
@@ -68,11 +68,11 @@ struct psai {
 };
 
 struct es7000_mem_info {
-       unsigned char type;   
+       unsigned char type;
        unsigned char length;
        unsigned char resv[6];
-       unsigned long long  start; 
-       unsigned long long  size; 
+       unsigned long long  start;
+       unsigned long long  size;
 };
 
 struct es7000_oem_table {
@@ -106,7 +106,7 @@ struct mip_reg {
 };
 
 #define        MIP_SW_APIC             0x1020b
-#define        MIP_FUNC(VALUE)         (VALUE & 0xff)
+#define        MIP_FUNC(VALUE)         (VALUE & 0xff)
 
 extern int parse_unisys_oem (char *oemptr);
 extern void setup_unisys(void);
similarity index 99%
rename from arch/x86/mach-es7000/es7000plat.c
rename to arch/x86/es7000/es7000plat.c
index 50189af14b859c67da06815b06a44c50ce07e4d8..7789fde13c3fc21a07eb63437c7c16f2b0c87d08 100644 (file)
@@ -72,7 +72,7 @@ es7000_rename_gsi(int ioapic, int gsi)
                        base += nr_ioapic_registers[i];
        }
 
-       if (!ioapic && (gsi < 16)) 
+       if (!ioapic && (gsi < 16))
                gsi += base;
        return gsi;
 }
index 3db651fc8ec5828468355151fae160ae65b7a267..a07ec14f33122c5531586d15a7e48251f31f9464 100644 (file)
@@ -104,6 +104,8 @@ obj-$(CONFIG_OLPC)          += olpc.o
 ifeq ($(CONFIG_X86_64),y)
         obj-y                          += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o
        obj-y                           += bios_uv.o
+        obj-y                          += genx2apic_cluster.o
+        obj-y                          += genx2apic_phys.o
         obj-$(CONFIG_X86_PM_TIMER)     += pmtimer_64.o
         obj-$(CONFIG_AUDIT)            += audit_64.o
 
index fa88a1d7129094fcc85b1b2425234a80e2418581..12e260e8fb2a9c35a2434bf13d156187191fc257 100644 (file)
@@ -761,7 +761,7 @@ static void __init acpi_register_lapic_address(unsigned long address)
 
        set_fixmap_nocache(FIX_APIC_BASE, address);
        if (boot_cpu_physical_apicid == -1U) {
-               boot_cpu_physical_apicid  = GET_APIC_ID(read_apic_id());
+               boot_cpu_physical_apicid  = read_apic_id();
 #ifdef CONFIG_X86_32
                apic_version[boot_cpu_physical_apicid] =
                         GET_APIC_VERSION(apic_read(APIC_LVR));
@@ -1337,7 +1337,9 @@ static void __init acpi_process_madt(void)
                                acpi_ioapic = 1;
 
                                smp_found_config = 1;
+#ifdef CONFIG_X86_32
                                setup_apic_routing();
+#endif
                        }
                }
                if (error == -EINVAL) {
index 039a8d4aaf62db88eeb36040ad15ff64be9ed852..84318edad8fbaf92af03638f399b7d974e98efa2 100644 (file)
@@ -145,13 +145,18 @@ static int modern_apic(void)
        return lapic_get_version() >= 0x14;
 }
 
-void apic_wait_icr_idle(void)
+/*
+ * Paravirt kernels also might be using these below ops. So we still
+ * use generic apic_read()/apic_write(), which might be pointing to different
+ * ops in PARAVIRT case.
+ */
+void xapic_wait_icr_idle(void)
 {
        while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
                cpu_relax();
 }
 
-u32 safe_apic_wait_icr_idle(void)
+u32 safe_xapic_wait_icr_idle(void)
 {
        u32 send_status;
        int timeout;
@@ -167,6 +172,34 @@ u32 safe_apic_wait_icr_idle(void)
        return send_status;
 }
 
+void xapic_icr_write(u32 low, u32 id)
+{
+       apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id));
+       apic_write(APIC_ICR, low);
+}
+
+u64 xapic_icr_read(void)
+{
+       u32 icr1, icr2;
+
+       icr2 = apic_read(APIC_ICR2);
+       icr1 = apic_read(APIC_ICR);
+
+       return icr1 | ((u64)icr2 << 32);
+}
+
+static struct apic_ops xapic_ops = {
+       .read = native_apic_mem_read,
+       .write = native_apic_mem_write,
+       .icr_read = xapic_icr_read,
+       .icr_write = xapic_icr_write,
+       .wait_icr_idle = xapic_wait_icr_idle,
+       .safe_wait_icr_idle = safe_xapic_wait_icr_idle,
+};
+
+struct apic_ops __read_mostly *apic_ops = &xapic_ops;
+EXPORT_SYMBOL_GPL(apic_ops);
+
 /**
  * enable_NMI_through_LVT0 - enable NMI through local vector table 0
  */
@@ -1205,7 +1238,7 @@ void __init init_apic_mappings(void)
         * default configuration (or the MP table is broken).
         */
        if (boot_cpu_physical_apicid == -1U)
-               boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+               boot_cpu_physical_apicid = read_apic_id();
 
 }
 
@@ -1242,7 +1275,7 @@ int __init APIC_init_uniprocessor(void)
         * might be zero if read from MP tables. Get it from LAPIC.
         */
 #ifdef CONFIG_CRASH_DUMP
-       boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+       boot_cpu_physical_apicid = read_apic_id();
 #endif
        physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
 
@@ -1321,54 +1354,6 @@ void smp_error_interrupt(struct pt_regs *regs)
        irq_exit();
 }
 
-#ifdef CONFIG_SMP
-void __init smp_intr_init(void)
-{
-       /*
-        * IRQ0 must be given a fixed assignment and initialized,
-        * because it's used before the IO-APIC is set up.
-        */
-       set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
-
-       /*
-        * The reschedule interrupt is a CPU-to-CPU reschedule-helper
-        * IPI, driven by wakeup.
-        */
-       alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
-
-       /* IPI for invalidation */
-       alloc_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
-
-       /* IPI for generic function call */
-       alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
-
-       /* IPI for single call function */
-       set_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
-                               call_function_single_interrupt);
-}
-#endif
-
-/*
- * Initialize APIC interrupts
- */
-void __init apic_intr_init(void)
-{
-#ifdef CONFIG_SMP
-       smp_intr_init();
-#endif
-       /* self generated IPI for local APIC timer */
-       alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
-       /* IPI vectors for APIC spurious and error interrupts */
-       alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
-       alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
-
-       /* thermal monitor LVT interrupt */
-#ifdef CONFIG_X86_MCE_P4THERMAL
-       alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
-#endif
-}
-
 /**
  * connect_bsp_APIC - attach the APIC to the interrupt system
  */
index 7f1f030da7ee4c048990eecf9dc00229472028ca..cd63c0bc61802a5415a3f8917af5e02bffd459ed 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/clockchips.h>
 #include <linux/acpi_pmtmr.h>
 #include <linux/module.h>
+#include <linux/dmar.h>
 
 #include <asm/atomic.h>
 #include <asm/smp.h>
@@ -39,6 +40,7 @@
 #include <asm/proto.h>
 #include <asm/timex.h>
 #include <asm/apic.h>
+#include <asm/i8259.h>
 
 #include <mach_ipi.h>
 #include <mach_apic.h>
 static int disable_apic_timer __cpuinitdata;
 static int apic_calibrate_pmtmr __initdata;
 int disable_apic;
+int disable_x2apic;
+int x2apic;
+
+/* x2apic enabled before OS handover */
+int x2apic_preenabled;
 
 /* Local APIC timer works in C2 */
 int local_apic_timer_c2_ok;
@@ -119,13 +126,13 @@ static int modern_apic(void)
        return lapic_get_version() >= 0x14;
 }
 
-void apic_wait_icr_idle(void)
+void xapic_wait_icr_idle(void)
 {
        while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
                cpu_relax();
 }
 
-u32 safe_apic_wait_icr_idle(void)
+u32 safe_xapic_wait_icr_idle(void)
 {
        u32 send_status;
        int timeout;
@@ -141,6 +148,69 @@ u32 safe_apic_wait_icr_idle(void)
        return send_status;
 }
 
+void xapic_icr_write(u32 low, u32 id)
+{
+       apic_write(APIC_ICR2, id << 24);
+       apic_write(APIC_ICR, low);
+}
+
+u64 xapic_icr_read(void)
+{
+       u32 icr1, icr2;
+
+       icr2 = apic_read(APIC_ICR2);
+       icr1 = apic_read(APIC_ICR);
+
+       return (icr1 | ((u64)icr2 << 32));
+}
+
+static struct apic_ops xapic_ops = {
+       .read = native_apic_mem_read,
+       .write = native_apic_mem_write,
+       .icr_read = xapic_icr_read,
+       .icr_write = xapic_icr_write,
+       .wait_icr_idle = xapic_wait_icr_idle,
+       .safe_wait_icr_idle = safe_xapic_wait_icr_idle,
+};
+
+struct apic_ops __read_mostly *apic_ops = &xapic_ops;
+
+EXPORT_SYMBOL_GPL(apic_ops);
+
+static void x2apic_wait_icr_idle(void)
+{
+       /* no need to wait for icr idle in x2apic */
+       return;
+}
+
+static u32 safe_x2apic_wait_icr_idle(void)
+{
+       /* no need to wait for icr idle in x2apic */
+       return 0;
+}
+
+void x2apic_icr_write(u32 low, u32 id)
+{
+       wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low);
+}
+
+u64 x2apic_icr_read(void)
+{
+       unsigned long val;
+
+       rdmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), val);
+       return val;
+}
+
+static struct apic_ops x2apic_ops = {
+       .read = native_apic_msr_read,
+       .write = native_apic_msr_write,
+       .icr_read = x2apic_icr_read,
+       .icr_write = x2apic_icr_write,
+       .wait_icr_idle = x2apic_wait_icr_idle,
+       .safe_wait_icr_idle = safe_x2apic_wait_icr_idle,
+};
+
 /**
  * enable_NMI_through_LVT0 - enable NMI through local vector table 0
  */
@@ -630,10 +700,10 @@ int __init verify_local_APIC(void)
        /*
         * The ID register is read/write in a real APIC.
         */
-       reg0 = read_apic_id();
+       reg0 = apic_read(APIC_ID);
        apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
        apic_write(APIC_ID, reg0 ^ APIC_ID_MASK);
-       reg1 = read_apic_id();
+       reg1 = apic_read(APIC_ID);
        apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1);
        apic_write(APIC_ID, reg0);
        if (reg1 != (reg0 ^ APIC_ID_MASK))
@@ -834,6 +904,125 @@ void __cpuinit end_local_APIC_setup(void)
        apic_pm_activate();
 }
 
+void check_x2apic(void)
+{
+       int msr, msr2;
+
+       rdmsr(MSR_IA32_APICBASE, msr, msr2);
+
+       if (msr & X2APIC_ENABLE) {
+               printk("x2apic enabled by BIOS, switching to x2apic ops\n");
+               x2apic_preenabled = x2apic = 1;
+               apic_ops = &x2apic_ops;
+       }
+}
+
+void enable_x2apic(void)
+{
+       int msr, msr2;
+
+       rdmsr(MSR_IA32_APICBASE, msr, msr2);
+       if (!(msr & X2APIC_ENABLE)) {
+               printk("Enabling x2apic\n");
+               wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
+       }
+}
+
+void enable_IR_x2apic(void)
+{
+#ifdef CONFIG_INTR_REMAP
+       int ret;
+       unsigned long flags;
+
+       if (!cpu_has_x2apic)
+               return;
+
+       if (!x2apic_preenabled && disable_x2apic) {
+               printk(KERN_INFO
+                      "Skipped enabling x2apic and Interrupt-remapping "
+                      "because of nox2apic\n");
+               return;
+       }
+
+       if (x2apic_preenabled && disable_x2apic)
+               panic("Bios already enabled x2apic, can't enforce nox2apic");
+
+       if (!x2apic_preenabled && skip_ioapic_setup) {
+               printk(KERN_INFO
+                      "Skipped enabling x2apic and Interrupt-remapping "
+                      "because of skipping io-apic setup\n");
+               return;
+       }
+
+       ret = dmar_table_init();
+       if (ret) {
+               printk(KERN_INFO
+                      "dmar_table_init() failed with %d:\n", ret);
+
+               if (x2apic_preenabled)
+                       panic("x2apic enabled by bios. But IR enabling failed");
+               else
+                       printk(KERN_INFO
+                              "Not enabling x2apic,Intr-remapping\n");
+               return;
+       }
+
+       local_irq_save(flags);
+       mask_8259A();
+       save_mask_IO_APIC_setup();
+
+       ret = enable_intr_remapping(1);
+
+       if (ret && x2apic_preenabled) {
+               local_irq_restore(flags);
+               panic("x2apic enabled by bios. But IR enabling failed");
+       }
+
+       if (ret)
+               goto end;
+
+       if (!x2apic) {
+               x2apic = 1;
+               apic_ops = &x2apic_ops;
+               enable_x2apic();
+       }
+end:
+       if (ret)
+               /*
+                * IR enabling failed
+                */
+               restore_IO_APIC_setup();
+       else
+               reinit_intr_remapped_IO_APIC(x2apic_preenabled);
+
+       unmask_8259A();
+       local_irq_restore(flags);
+
+       if (!ret) {
+               if (!x2apic_preenabled)
+                       printk(KERN_INFO
+                              "Enabled x2apic and interrupt-remapping\n");
+               else
+                       printk(KERN_INFO
+                              "Enabled Interrupt-remapping\n");
+       } else
+               printk(KERN_ERR
+                      "Failed to enable Interrupt-remapping and x2apic\n");
+#else
+       if (!cpu_has_x2apic)
+               return;
+
+       if (x2apic_preenabled)
+               panic("x2apic enabled prior OS handover,"
+                     " enable CONFIG_INTR_REMAP");
+
+       printk(KERN_INFO "Enable CONFIG_INTR_REMAP for enabling intr-remapping "
+              " and x2apic\n");
+#endif
+
+       return;
+}
+
 /*
  * Detect and enable local APICs on non-SMP boards.
  * Original code written by Keir Fraser.
@@ -873,7 +1062,7 @@ void __init early_init_lapic_mapping(void)
         * Fetch the APIC ID of the BSP in case we have a
         * default configuration (or the MP table is broken).
         */
-       boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+       boot_cpu_physical_apicid = read_apic_id();
 }
 
 /**
@@ -881,6 +1070,11 @@ void __init early_init_lapic_mapping(void)
  */
 void __init init_apic_mappings(void)
 {
+       if (x2apic) {
+               boot_cpu_physical_apicid = read_apic_id();
+               return;
+       }
+
        /*
         * If no local APIC can be found then set up a fake all
         * zeroes page to simulate the local APIC and another
@@ -900,7 +1094,7 @@ void __init init_apic_mappings(void)
         * Fetch the APIC ID of the BSP in case we have a
         * default configuration (or the MP table is broken).
         */
-       boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+       boot_cpu_physical_apicid = read_apic_id();
 }
 
 /*
@@ -919,6 +1113,9 @@ int __init APIC_init_uniprocessor(void)
                return -1;
        }
 
+       enable_IR_x2apic();
+       setup_apic_routing();
+
        verify_local_APIC();
 
        connect_bsp_APIC();
@@ -1100,6 +1297,11 @@ void __cpuinit generic_processor_info(int apicid, int version)
        cpu_set(cpu, cpu_present_map);
 }
 
+int hard_smp_processor_id(void)
+{
+       return read_apic_id();
+}
+
 /*
  * Power management
  */
@@ -1136,7 +1338,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
 
        maxlvt = lapic_get_maxlvt();
 
-       apic_pm_state.apic_id = read_apic_id();
+       apic_pm_state.apic_id = apic_read(APIC_ID);
        apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
        apic_pm_state.apic_ldr = apic_read(APIC_LDR);
        apic_pm_state.apic_dfr = apic_read(APIC_DFR);
@@ -1171,10 +1373,14 @@ static int lapic_resume(struct sys_device *dev)
        maxlvt = lapic_get_maxlvt();
 
        local_irq_save(flags);
-       rdmsr(MSR_IA32_APICBASE, l, h);
-       l &= ~MSR_IA32_APICBASE_BASE;
-       l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
-       wrmsr(MSR_IA32_APICBASE, l, h);
+       if (!x2apic) {
+               rdmsr(MSR_IA32_APICBASE, l, h);
+               l &= ~MSR_IA32_APICBASE_BASE;
+               l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
+               wrmsr(MSR_IA32_APICBASE, l, h);
+       } else
+               enable_x2apic();
+
        apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
        apic_write(APIC_ID, apic_pm_state.apic_id);
        apic_write(APIC_DFR, apic_pm_state.apic_dfr);
@@ -1314,6 +1520,15 @@ __cpuinit int apic_is_clustered_box(void)
        return (clusters > 2);
 }
 
+static __init int setup_nox2apic(char *str)
+{
+       disable_x2apic = 1;
+       clear_cpu_cap(&boot_cpu_data, X86_FEATURE_X2APIC);
+       return 0;
+}
+early_param("nox2apic", setup_nox2apic);
+
+
 /*
  * APIC command line parameters
  */
index aa89387006fe3a730b9b7eba9b7b55cc3c1beb4d..505543a75a561f1cfc207d4f88dffbd2718bc724 100644 (file)
@@ -22,7 +22,7 @@
 
 #define __NO_STUBS 1
 #undef __SYSCALL
-#undef _ASM_X86_64_UNISTD_H_
+#undef ASM_X86__UNISTD_64_H
 #define __SYSCALL(nr, sym) [nr] = 1,
 static char syscalls[] = {
 #include <asm/unistd.h>
index dd6e3f15017eb87b04885fd5164681bbdd9a3073..cc6efe86249d3490059d1340799d92d6e95992ca 100644 (file)
@@ -493,17 +493,20 @@ void pda_init(int cpu)
                /* others are initialized in smpboot.c */
                pda->pcurrent = &init_task;
                pda->irqstackptr = boot_cpu_stack;
+               pda->irqstackptr += IRQSTACKSIZE - 64;
        } else {
-               pda->irqstackptr = (char *)
-                       __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
-               if (!pda->irqstackptr)
-                       panic("cannot allocate irqstack for cpu %d", cpu);
+               if (!pda->irqstackptr) {
+                       pda->irqstackptr = (char *)
+                               __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
+                       if (!pda->irqstackptr)
+                               panic("cannot allocate irqstack for cpu %d",
+                                     cpu);
+                       pda->irqstackptr += IRQSTACKSIZE - 64;
+               }
 
                if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE)
                        pda->nodenumber = cpu_to_node(cpu);
        }
-
-       pda->irqstackptr += IRQSTACKSIZE-64;
 }
 
 char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
@@ -597,23 +600,28 @@ void __cpuinit cpu_init(void)
        barrier();
 
        check_efer();
+       if (cpu != 0 && x2apic)
+               enable_x2apic();
 
        /*
         * set up and load the per-CPU TSS
         */
-       for (v = 0; v < N_EXCEPTION_STACKS; v++) {
+       if (!orig_ist->ist[0]) {
                static const unsigned int order[N_EXCEPTION_STACKS] = {
-                       [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
-                       [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
+                 [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
+                 [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
                };
-               if (cpu) {
-                       estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
-                       if (!estacks)
-                               panic("Cannot allocate exception stack %ld %d\n",
-                                     v, cpu);
+               for (v = 0; v < N_EXCEPTION_STACKS; v++) {
+                       if (cpu) {
+                               estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
+                               if (!estacks)
+                                       panic("Cannot allocate exception "
+                                             "stack %ld %d\n", v, cpu);
+                       }
+                       estacks += PAGE_SIZE << order[v];
+                       orig_ist->ist[v] = t->x86_tss.ist[v] =
+                                       (unsigned long)estacks;
                }
-               estacks += PAGE_SIZE << order[v];
-               orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks;
        }
 
        t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
index e43ad4ad4cbae8b75561f67ec1da51628c568491..0bf4d37a04833e5b5532fa497453eb6410938130 100644 (file)
@@ -45,7 +45,7 @@ const char * const x86_cap_flags[NCAPINTS*32] = {
        /* Intel-defined (#2) */
        "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
        "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
-       NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt",
+       NULL, NULL, "dca", "sse4_1", "sse4_2", "x2apic", NULL, "popcnt",
        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
        /* VIA/Cyrix/Centaur-defined */
index 89434d439605484b48a7b26ba31c55e82c9821c5..cf3a0b2d00599adb2a79fefa991c0d8223059fba 100644 (file)
@@ -275,9 +275,9 @@ ENTRY(native_usergs_sysret64)
 ENTRY(ret_from_fork)
        CFI_DEFAULT_STACK
        push kernel_eflags(%rip)
-       CFI_ADJUST_CFA_OFFSET 4
+       CFI_ADJUST_CFA_OFFSET 8
        popf                            # reset kernel eflags
-       CFI_ADJUST_CFA_OFFSET -4
+       CFI_ADJUST_CFA_OFFSET -8
        call schedule_tail
        GET_THREAD_INFO(%rcx)
        testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
index eaff0bbb1444b73d7110782130ec78ed12f9e520..6c9bfc9e1e95cbc5f8aa2273bd06f9eb75c2ca11 100644 (file)
 #include <linux/ctype.h>
 #include <linux/init.h>
 #include <linux/hardirq.h>
+#include <linux/dmar.h>
 
 #include <asm/smp.h>
 #include <asm/ipi.h>
 #include <asm/genapic.h>
 
-#ifdef CONFIG_ACPI
-#include <acpi/acpi_bus.h>
-#endif
-
-DEFINE_PER_CPU(int, x2apic_extra_bits);
+extern struct genapic apic_flat;
+extern struct genapic apic_physflat;
+extern struct genapic apic_x2xpic_uv_x;
+extern struct genapic apic_x2apic_phys;
+extern struct genapic apic_x2apic_cluster;
 
 struct genapic __read_mostly *genapic = &apic_flat;
 
-static enum uv_system_type uv_system_type;
+static struct genapic *apic_probe[] __initdata = {
+       &apic_x2apic_uv_x,
+       &apic_x2apic_phys,
+       &apic_x2apic_cluster,
+       &apic_physflat,
+       NULL,
+};
 
 /*
  * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
  */
 void __init setup_apic_routing(void)
 {
-       if (uv_system_type == UV_NON_UNIQUE_APIC)
-               genapic = &apic_x2apic_uv_x;
-       else
-#ifdef CONFIG_ACPI
-       /*
-        * Quirk: some x86_64 machines can only use physical APIC mode
-        * regardless of how many processors are present (x86_64 ES7000
-        * is an example).
-        */
-       if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
-                       (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL))
-               genapic = &apic_physflat;
-       else
-#endif
-
-       if (max_physical_apicid < 8)
-               genapic = &apic_flat;
-       else
-               genapic = &apic_physflat;
+       if (genapic == &apic_x2apic_phys || genapic == &apic_x2apic_cluster) {
+               if (!intr_remapping_enabled)
+                       genapic = &apic_flat;
+       }
 
-       printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
+       if (genapic == &apic_flat) {
+               if (max_physical_apicid >= 8)
+                       genapic = &apic_physflat;
+               printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
+       }
 }
 
 /* Same for both flat and physical. */
 
-void send_IPI_self(int vector)
+void apic_send_IPI_self(int vector)
 {
        __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
 }
 
 int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
-       if (!strcmp(oem_id, "SGI")) {
-               if (!strcmp(oem_table_id, "UVL"))
-                       uv_system_type = UV_LEGACY_APIC;
-               else if (!strcmp(oem_table_id, "UVX"))
-                       uv_system_type = UV_X2APIC;
-               else if (!strcmp(oem_table_id, "UVH"))
-                       uv_system_type = UV_NON_UNIQUE_APIC;
+       int i;
+
+       for (i = 0; apic_probe[i]; ++i) {
+               if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
+                       genapic = apic_probe[i];
+                       printk(KERN_INFO "Setting APIC routing to %s.\n",
+                               genapic->name);
+                       return 1;
+               }
        }
        return 0;
 }
-
-unsigned int read_apic_id(void)
-{
-       unsigned int id;
-
-       WARN_ON(preemptible() && num_online_cpus() > 1);
-       id = apic_read(APIC_ID);
-       if (uv_system_type >= UV_X2APIC)
-               id  |= __get_cpu_var(x2apic_extra_bits);
-       return id;
-}
-
-enum uv_system_type get_uv_system_type(void)
-{
-       return uv_system_type;
-}
-
-int is_uv_system(void)
-{
-       return uv_system_type != UV_NONE;
-}
-EXPORT_SYMBOL_GPL(is_uv_system);
index 786548a62d381b1b65af8651c912d491d2178f2c..9eca5ba7a6b1dcfe543fc644ab049e40b9139a9f 100644 (file)
 #include <linux/kernel.h>
 #include <linux/ctype.h>
 #include <linux/init.h>
+#include <linux/hardirq.h>
 #include <asm/smp.h>
 #include <asm/ipi.h>
 #include <asm/genapic.h>
+#include <mach_apicdef.h>
+
+#ifdef CONFIG_ACPI
+#include <acpi/acpi_bus.h>
+#endif
+
+static int __init flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+       return 1;
+}
 
 static cpumask_t flat_target_cpus(void)
 {
@@ -95,9 +106,33 @@ static void flat_send_IPI_all(int vector)
                __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
 }
 
+static unsigned int get_apic_id(unsigned long x)
+{
+       unsigned int id;
+
+       id = (((x)>>24) & 0xFFu);
+       return id;
+}
+
+static unsigned long set_apic_id(unsigned int id)
+{
+       unsigned long x;
+
+       x = ((id & 0xFFu)<<24);
+       return x;
+}
+
+static unsigned int read_xapic_id(void)
+{
+       unsigned int id;
+
+       id = get_apic_id(apic_read(APIC_ID));
+       return id;
+}
+
 static int flat_apic_id_registered(void)
 {
-       return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map);
+       return physid_isset(read_xapic_id(), phys_cpu_present_map);
 }
 
 static unsigned int flat_cpu_mask_to_apicid(cpumask_t cpumask)
@@ -112,6 +147,7 @@ static unsigned int phys_pkg_id(int index_msb)
 
 struct genapic apic_flat =  {
        .name = "flat",
+       .acpi_madt_oem_check = flat_acpi_madt_oem_check,
        .int_delivery_mode = dest_LowestPrio,
        .int_dest_mode = (APIC_DEST_LOGICAL != 0),
        .target_cpus = flat_target_cpus,
@@ -121,8 +157,12 @@ struct genapic apic_flat =  {
        .send_IPI_all = flat_send_IPI_all,
        .send_IPI_allbutself = flat_send_IPI_allbutself,
        .send_IPI_mask = flat_send_IPI_mask,
+       .send_IPI_self = apic_send_IPI_self,
        .cpu_mask_to_apicid = flat_cpu_mask_to_apicid,
        .phys_pkg_id = phys_pkg_id,
+       .get_apic_id = get_apic_id,
+       .set_apic_id = set_apic_id,
+       .apic_id_mask = (0xFFu<<24),
 };
 
 /*
@@ -130,6 +170,21 @@ struct genapic apic_flat =  {
  * We cannot use logical delivery in this case because the mask
  * overflows, so use physical mode.
  */
+static int __init physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+#ifdef CONFIG_ACPI
+       /*
+        * Quirk: some x86_64 machines can only use physical APIC mode
+        * regardless of how many processors are present (x86_64 ES7000
+        * is an example).
+        */
+       if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
+               (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL))
+               return 1;
+#endif
+
+       return 0;
+}
 
 static cpumask_t physflat_target_cpus(void)
 {
@@ -176,6 +231,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
 
 struct genapic apic_physflat =  {
        .name = "physical flat",
+       .acpi_madt_oem_check = physflat_acpi_madt_oem_check,
        .int_delivery_mode = dest_Fixed,
        .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
        .target_cpus = physflat_target_cpus,
@@ -185,6 +241,10 @@ struct genapic apic_physflat =  {
        .send_IPI_all = physflat_send_IPI_all,
        .send_IPI_allbutself = physflat_send_IPI_allbutself,
        .send_IPI_mask = physflat_send_IPI_mask,
+       .send_IPI_self = apic_send_IPI_self,
        .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid,
        .phys_pkg_id = phys_pkg_id,
+       .get_apic_id = get_apic_id,
+       .set_apic_id = set_apic_id,
+       .apic_id_mask = (0xFFu<<24),
 };
diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c
new file mode 100644 (file)
index 0000000..fed9f68
--- /dev/null
@@ -0,0 +1,164 @@
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/dmar.h>
+
+#include <asm/smp.h>
+#include <asm/ipi.h>
+#include <asm/genapic.h>
+
+DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid);
+
+static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+       if (cpu_has_x2apic)
+               return 1;
+
+       return 0;
+}
+
+/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
+
+static cpumask_t x2apic_target_cpus(void)
+{
+       return cpumask_of_cpu(0);
+}
+
+/*
+ * for now each logical cpu is in its own vector allocation domain.
+ */
+static cpumask_t x2apic_vector_allocation_domain(int cpu)
+{
+       cpumask_t domain = CPU_MASK_NONE;
+       cpu_set(cpu, domain);
+       return domain;
+}
+
+static void __x2apic_send_IPI_dest(unsigned int apicid, int vector,
+                                  unsigned int dest)
+{
+       unsigned long cfg;
+
+       cfg = __prepare_ICR(0, vector, dest);
+
+       /*
+        * send the IPI.
+        */
+       x2apic_icr_write(cfg, apicid);
+}
+
+/*
+ * for now, we send the IPI's one by one in the cpumask.
+ * TBD: Based on the cpu mask, we can send the IPI's to the cluster group
+ * at once. We have 16 cpu's in a cluster. This will minimize IPI register
+ * writes.
+ */
+static void x2apic_send_IPI_mask(cpumask_t mask, int vector)
+{
+       unsigned long flags;
+       unsigned long query_cpu;
+
+       local_irq_save(flags);
+       for_each_cpu_mask(query_cpu, mask) {
+               __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_logical_apicid, query_cpu),
+                                      vector, APIC_DEST_LOGICAL);
+       }
+       local_irq_restore(flags);
+}
+
+static void x2apic_send_IPI_allbutself(int vector)
+{
+       cpumask_t mask = cpu_online_map;
+
+       cpu_clear(smp_processor_id(), mask);
+
+       if (!cpus_empty(mask))
+               x2apic_send_IPI_mask(mask, vector);
+}
+
+static void x2apic_send_IPI_all(int vector)
+{
+       x2apic_send_IPI_mask(cpu_online_map, vector);
+}
+
+static int x2apic_apic_id_registered(void)
+{
+       return 1;
+}
+
+static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask)
+{
+       int cpu;
+
+       /*
+        * We're using fixed IRQ delivery, can only return one phys APIC ID.
+        * May as well be the first.
+        */
+       cpu = first_cpu(cpumask);
+       if ((unsigned)cpu < NR_CPUS)
+               return per_cpu(x86_cpu_to_logical_apicid, cpu);
+       else
+               return BAD_APICID;
+}
+
+static unsigned int get_apic_id(unsigned long x)
+{
+       unsigned int id;
+
+       id = x;
+       return id;
+}
+
+static unsigned long set_apic_id(unsigned int id)
+{
+       unsigned long x;
+
+       x = id;
+       return x;
+}
+
+static unsigned int x2apic_read_id(void)
+{
+       return apic_read(APIC_ID);
+}
+
+static unsigned int phys_pkg_id(int index_msb)
+{
+       return x2apic_read_id() >> index_msb;
+}
+
+static void x2apic_send_IPI_self(int vector)
+{
+       apic_write(APIC_SELF_IPI, vector);
+}
+
+static void init_x2apic_ldr(void)
+{
+       int cpu = smp_processor_id();
+
+       per_cpu(x86_cpu_to_logical_apicid, cpu) = apic_read(APIC_LDR);
+       return;
+}
+
+struct genapic apic_x2apic_cluster = {
+       .name = "cluster x2apic",
+       .acpi_madt_oem_check = x2apic_acpi_madt_oem_check,
+       .int_delivery_mode = dest_LowestPrio,
+       .int_dest_mode = (APIC_DEST_LOGICAL != 0),
+       .target_cpus = x2apic_target_cpus,
+       .vector_allocation_domain = x2apic_vector_allocation_domain,
+       .apic_id_registered = x2apic_apic_id_registered,
+       .init_apic_ldr = init_x2apic_ldr,
+       .send_IPI_all = x2apic_send_IPI_all,
+       .send_IPI_allbutself = x2apic_send_IPI_allbutself,
+       .send_IPI_mask = x2apic_send_IPI_mask,
+       .send_IPI_self = x2apic_send_IPI_self,
+       .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid,
+       .phys_pkg_id = phys_pkg_id,
+       .get_apic_id = get_apic_id,
+       .set_apic_id = set_apic_id,
+       .apic_id_mask = (0xFFFFFFFFu),
+};
diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c
new file mode 100644 (file)
index 0000000..958d537
--- /dev/null
@@ -0,0 +1,159 @@
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/dmar.h>
+
+#include <asm/smp.h>
+#include <asm/ipi.h>
+#include <asm/genapic.h>
+
+static int x2apic_phys;
+
+static int set_x2apic_phys_mode(char *arg)
+{
+       x2apic_phys = 1;
+       return 0;
+}
+early_param("x2apic_phys", set_x2apic_phys_mode);
+
+static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+       if (cpu_has_x2apic && x2apic_phys)
+               return 1;
+
+       return 0;
+}
+
+/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
+
+static cpumask_t x2apic_target_cpus(void)
+{
+       return cpumask_of_cpu(0);
+}
+
+static cpumask_t x2apic_vector_allocation_domain(int cpu)
+{
+       cpumask_t domain = CPU_MASK_NONE;
+       cpu_set(cpu, domain);
+       return domain;
+}
+
+static void __x2apic_send_IPI_dest(unsigned int apicid, int vector,
+                                  unsigned int dest)
+{
+       unsigned long cfg;
+
+       cfg = __prepare_ICR(0, vector, dest);
+
+       /*
+        * send the IPI.
+        */
+       x2apic_icr_write(cfg, apicid);
+}
+
+static void x2apic_send_IPI_mask(cpumask_t mask, int vector)
+{
+       unsigned long flags;
+       unsigned long query_cpu;
+
+       local_irq_save(flags);
+       for_each_cpu_mask(query_cpu, mask) {
+               __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu),
+                                      vector, APIC_DEST_PHYSICAL);
+       }
+       local_irq_restore(flags);
+}
+
+static void x2apic_send_IPI_allbutself(int vector)
+{
+       cpumask_t mask = cpu_online_map;
+
+       cpu_clear(smp_processor_id(), mask);
+
+       if (!cpus_empty(mask))
+               x2apic_send_IPI_mask(mask, vector);
+}
+
+static void x2apic_send_IPI_all(int vector)
+{
+       x2apic_send_IPI_mask(cpu_online_map, vector);
+}
+
+static int x2apic_apic_id_registered(void)
+{
+       return 1;
+}
+
+static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask)
+{
+       int cpu;
+
+       /*
+        * We're using fixed IRQ delivery, can only return one phys APIC ID.
+        * May as well be the first.
+        */
+       cpu = first_cpu(cpumask);
+       if ((unsigned)cpu < NR_CPUS)
+               return per_cpu(x86_cpu_to_apicid, cpu);
+       else
+               return BAD_APICID;
+}
+
+static unsigned int get_apic_id(unsigned long x)
+{
+       unsigned int id;
+
+       id = x;
+       return id;
+}
+
+static unsigned long set_apic_id(unsigned int id)
+{
+       unsigned long x;
+
+       x = id;
+       return x;
+}
+
+static unsigned int x2apic_read_id(void)
+{
+       return apic_read(APIC_ID);
+}
+
+static unsigned int phys_pkg_id(int index_msb)
+{
+       return x2apic_read_id() >> index_msb;
+}
+
+void x2apic_send_IPI_self(int vector)
+{
+       apic_write(APIC_SELF_IPI, vector);
+}
+
+void init_x2apic_ldr(void)
+{
+       return;
+}
+
+struct genapic apic_x2apic_phys = {
+       .name = "physical x2apic",
+       .acpi_madt_oem_check = x2apic_acpi_madt_oem_check,
+       .int_delivery_mode = dest_Fixed,
+       .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
+       .target_cpus = x2apic_target_cpus,
+       .vector_allocation_domain = x2apic_vector_allocation_domain,
+       .apic_id_registered = x2apic_apic_id_registered,
+       .init_apic_ldr = init_x2apic_ldr,
+       .send_IPI_all = x2apic_send_IPI_all,
+       .send_IPI_allbutself = x2apic_send_IPI_allbutself,
+       .send_IPI_mask = x2apic_send_IPI_mask,
+       .send_IPI_self = x2apic_send_IPI_self,
+       .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid,
+       .phys_pkg_id = phys_pkg_id,
+       .get_apic_id = get_apic_id,
+       .set_apic_id = set_apic_id,
+       .apic_id_mask = (0xFFFFFFFFu),
+};
index 2cfcbded888a0b91eece817e0eb3f49e865154fd..16a93ed7baf185199180658360ca857c059eea70 100644 (file)
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/string.h>
-#include <linux/kernel.h>
 #include <linux/ctype.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/bootmem.h>
 #include <linux/module.h>
+#include <linux/hardirq.h>
 #include <asm/smp.h>
 #include <asm/ipi.h>
 #include <asm/genapic.h>
 #include <asm/uv/uv_hub.h>
 #include <asm/uv/bios.h>
 
+DEFINE_PER_CPU(int, x2apic_extra_bits);
+
+static enum uv_system_type uv_system_type;
+
+static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+       if (!strcmp(oem_id, "SGI")) {
+               if (!strcmp(oem_table_id, "UVL"))
+                       uv_system_type = UV_LEGACY_APIC;
+               else if (!strcmp(oem_table_id, "UVX"))
+                       uv_system_type = UV_X2APIC;
+               else if (!strcmp(oem_table_id, "UVH")) {
+                       uv_system_type = UV_NON_UNIQUE_APIC;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+enum uv_system_type get_uv_system_type(void)
+{
+       return uv_system_type;
+}
+
+int is_uv_system(void)
+{
+       return uv_system_type != UV_NONE;
+}
+EXPORT_SYMBOL_GPL(is_uv_system);
+
 DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
 EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info);
 
@@ -123,6 +153,10 @@ static int uv_apic_id_registered(void)
        return 1;
 }
 
+static void uv_init_apic_ldr(void)
+{
+}
+
 static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask)
 {
        int cpu;
@@ -138,9 +172,34 @@ static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask)
                return BAD_APICID;
 }
 
+static unsigned int get_apic_id(unsigned long x)
+{
+       unsigned int id;
+
+       WARN_ON(preemptible() && num_online_cpus() > 1);
+       id = x | __get_cpu_var(x2apic_extra_bits);
+
+       return id;
+}
+
+static unsigned long set_apic_id(unsigned int id)
+{
+       unsigned long x;
+
+       /* maskout x2apic_extra_bits ? */
+       x = id;
+       return x;
+}
+
+static unsigned int uv_read_apic_id(void)
+{
+
+       return get_apic_id(apic_read(APIC_ID));
+}
+
 static unsigned int phys_pkg_id(int index_msb)
 {
-       return GET_APIC_ID(read_apic_id()) >> index_msb;
+       return uv_read_apic_id() >> index_msb;
 }
 
 #ifdef ZZZ             /* Needs x2apic patch */
@@ -152,17 +211,22 @@ static void uv_send_IPI_self(int vector)
 
 struct genapic apic_x2apic_uv_x = {
        .name = "UV large system",
+       .acpi_madt_oem_check = uv_acpi_madt_oem_check,
        .int_delivery_mode = dest_Fixed,
        .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
        .target_cpus = uv_target_cpus,
        .vector_allocation_domain = uv_vector_allocation_domain,/* Fixme ZZZ */
        .apic_id_registered = uv_apic_id_registered,
+       .init_apic_ldr = uv_init_apic_ldr,
        .send_IPI_all = uv_send_IPI_all,
        .send_IPI_allbutself = uv_send_IPI_allbutself,
        .send_IPI_mask = uv_send_IPI_mask,
        /* ZZZ.send_IPI_self = uv_send_IPI_self, */
        .cpu_mask_to_apicid = uv_cpu_mask_to_apicid,
        .phys_pkg_id = phys_pkg_id,     /* Fixme ZZZ */
+       .get_apic_id = get_apic_id,
+       .set_apic_id = set_apic_id,
+       .apic_id_mask = (0xFFFFFFFFu),
 };
 
 static __cpuinit void set_x2apic_extra_bits(int pnode)
@@ -399,3 +463,5 @@ void __cpuinit uv_cpu_init(void)
        if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
                set_x2apic_extra_bits(uv_hub_info->pnode);
 }
+
+
index dc92b49d9204d59d181bcaf01c434446d55de39a..4b8a53d841f7a1c71e75eb85a9fe4ecacb17d4b3 100644 (file)
@@ -282,6 +282,30 @@ static int __init i8259A_init_sysfs(void)
 
 device_initcall(i8259A_init_sysfs);
 
+void mask_8259A(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&i8259A_lock, flags);
+
+       outb(0xff, PIC_MASTER_IMR);     /* mask all of 8259A-1 */
+       outb(0xff, PIC_SLAVE_IMR);      /* mask all of 8259A-2 */
+
+       spin_unlock_irqrestore(&i8259A_lock, flags);
+}
+
+void unmask_8259A(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&i8259A_lock, flags);
+
+       outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
+       outb(cached_slave_mask, PIC_SLAVE_IMR);   /* restore slave IRQ mask */
+
+       spin_unlock_irqrestore(&i8259A_lock, flags);
+}
+
 void init_8259A(int auto_eoi)
 {
        unsigned long flags;
index 09cddb57bec45e9ddd60ba376b3a70aca647ad8d..a0f4c27c822da91ed4630809b3b726606e4f65e9 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/nmi.h>
 #include <asm/msidef.h>
 #include <asm/hypertransport.h>
+#include <asm/setup.h>
 
 #include <mach_apic.h>
 #include <mach_apicdef.h>
@@ -1482,6 +1483,7 @@ static void print_APIC_bitfield(int base)
 void /*__init*/ print_local_APIC(void *dummy)
 {
        unsigned int v, ver, maxlvt;
+       u64 icr;
 
        if (apic_verbosity == APIC_QUIET)
                return;
@@ -1490,7 +1492,7 @@ void /*__init*/ print_local_APIC(void *dummy)
                smp_processor_id(), hard_smp_processor_id());
        v = apic_read(APIC_ID);
        printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v,
-                       GET_APIC_ID(read_apic_id()));
+                       GET_APIC_ID(v));
        v = apic_read(APIC_LVR);
        printk(KERN_INFO "... APIC VERSION: %08x\n", v);
        ver = GET_APIC_VERSION(v);
@@ -1532,10 +1534,9 @@ void /*__init*/ print_local_APIC(void *dummy)
                printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
        }
 
-       v = apic_read(APIC_ICR);
-       printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
-       v = apic_read(APIC_ICR2);
-       printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);
+       icr = apic_icr_read();
+       printk(KERN_DEBUG "... APIC ICR: %08x\n", icr);
+       printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32);
 
        v = apic_read(APIC_LVTT);
        printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
@@ -1698,8 +1699,7 @@ void disable_IO_APIC(void)
                entry.dest_mode       = 0; /* Physical */
                entry.delivery_mode   = dest_ExtINT; /* ExtInt */
                entry.vector          = 0;
-               entry.dest.physical.physical_dest =
-                                       GET_APIC_ID(read_apic_id());
+               entry.dest.physical.physical_dest = read_apic_id();
 
                /*
                 * Add it to the IO-APIC irq-routing table:
@@ -1725,10 +1725,8 @@ static void __init setup_ioapic_ids_from_mpc(void)
        unsigned char old_id;
        unsigned long flags;
 
-#ifdef CONFIG_X86_NUMAQ
-       if (found_numaq)
+       if (x86_quirks->setup_ioapic_ids && x86_quirks->setup_ioapic_ids())
                return;
-#endif
 
        /*
         * Don't check I/O APIC IDs for xAPIC systems.  They have
index 61a83b70c18fcc65ce60b965ee3a6e0456622dc4..e63282e788640402828dc17cf641a9a8c71c003a 100644 (file)
@@ -37,6 +37,7 @@
 #include <acpi/acpi_bus.h>
 #endif
 #include <linux/bootmem.h>
+#include <linux/dmar.h>
 
 #include <asm/idle.h>
 #include <asm/io.h>
@@ -49,6 +50,7 @@
 #include <asm/nmi.h>
 #include <asm/msidef.h>
 #include <asm/hypertransport.h>
+#include <asm/irq_remapping.h>
 
 #include <mach_ipi.h>
 #include <mach_apic.h>
@@ -108,6 +110,9 @@ static DEFINE_SPINLOCK(vector_lock);
  */
 int nr_ioapic_registers[MAX_IO_APICS];
 
+/* I/O APIC RTE contents at the OS boot up */
+struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
+
 /* I/O APIC entries */
 struct mp_config_ioapic mp_ioapics[MAX_IO_APICS];
 int nr_ioapics;
@@ -303,7 +308,12 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
                pin = entry->pin;
                if (pin == -1)
                        break;
-               io_apic_write(apic, 0x11 + pin*2, dest);
+               /*
+                * With interrupt-remapping, destination information comes
+                * from interrupt-remapping table entry.
+                */
+               if (!irq_remapped(irq))
+                       io_apic_write(apic, 0x11 + pin*2, dest);
                reg = io_apic_read(apic, 0x10 + pin*2);
                reg &= ~IO_APIC_REDIR_VECTOR_MASK;
                reg |= vector;
@@ -440,6 +450,69 @@ static void clear_IO_APIC (void)
                        clear_IO_APIC_pin(apic, pin);
 }
 
+/*
+ * Saves and masks all the unmasked IO-APIC RTE's
+ */
+int save_mask_IO_APIC_setup(void)
+{
+       union IO_APIC_reg_01 reg_01;
+       unsigned long flags;
+       int apic, pin;
+
+       /*
+        * The number of IO-APIC IRQ registers (== #pins):
+        */
+       for (apic = 0; apic < nr_ioapics; apic++) {
+               spin_lock_irqsave(&ioapic_lock, flags);
+               reg_01.raw = io_apic_read(apic, 1);
+               spin_unlock_irqrestore(&ioapic_lock, flags);
+               nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+       }
+
+       for (apic = 0; apic < nr_ioapics; apic++) {
+               early_ioapic_entries[apic] =
+                       kzalloc(sizeof(struct IO_APIC_route_entry) *
+                               nr_ioapic_registers[apic], GFP_KERNEL);
+               if (!early_ioapic_entries[apic])
+                       return -ENOMEM;
+       }
+
+       for (apic = 0; apic < nr_ioapics; apic++)
+               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+                       struct IO_APIC_route_entry entry;
+
+                       entry = early_ioapic_entries[apic][pin] =
+                               ioapic_read_entry(apic, pin);
+                       if (!entry.mask) {
+                               entry.mask = 1;
+                               ioapic_write_entry(apic, pin, entry);
+                       }
+               }
+       return 0;
+}
+
+void restore_IO_APIC_setup(void)
+{
+       int apic, pin;
+
+       for (apic = 0; apic < nr_ioapics; apic++)
+               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+                       ioapic_write_entry(apic, pin,
+                                          early_ioapic_entries[apic][pin]);
+}
+
+void reinit_intr_remapped_IO_APIC(int intr_remapping)
+{
+       /*
+        * for now plain restore of previous settings.
+        * TBD: In the case of OS enabling interrupt-remapping,
+        * IO-APIC RTE's need to be setup to point to interrupt-remapping
+        * table entries. for now, do a plain restore, and wait for
+        * the setup_IO_APIC_irqs() to do proper initialization.
+        */
+       restore_IO_APIC_setup();
+}
+
 int skip_ioapic_setup;
 int ioapic_force;
 
@@ -839,18 +912,98 @@ void __setup_vector_irq(int cpu)
 }
 
 static struct irq_chip ioapic_chip;
+#ifdef CONFIG_INTR_REMAP
+static struct irq_chip ir_ioapic_chip;
+#endif
 
 static void ioapic_register_intr(int irq, unsigned long trigger)
 {
-       if (trigger) {
+       if (trigger)
                irq_desc[irq].status |= IRQ_LEVEL;
-               set_irq_chip_and_handler_name(irq, &ioapic_chip,
-                                             handle_fasteoi_irq, "fasteoi");
-       } else {
+       else
                irq_desc[irq].status &= ~IRQ_LEVEL;
+
+#ifdef CONFIG_INTR_REMAP
+       if (irq_remapped(irq)) {
+               irq_desc[irq].status |= IRQ_MOVE_PCNTXT;
+               if (trigger)
+                       set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
+                                                     handle_fasteoi_irq,
+                                                    "fasteoi");
+               else
+                       set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
+                                                     handle_edge_irq, "edge");
+               return;
+       }
+#endif
+       if (trigger)
+               set_irq_chip_and_handler_name(irq, &ioapic_chip,
+                                             handle_fasteoi_irq,
+                                             "fasteoi");
+       else
                set_irq_chip_and_handler_name(irq, &ioapic_chip,
                                              handle_edge_irq, "edge");
+}
+
+static int setup_ioapic_entry(int apic, int irq,
+                             struct IO_APIC_route_entry *entry,
+                             unsigned int destination, int trigger,
+                             int polarity, int vector)
+{
+       /*
+        * add it to the IO-APIC irq-routing table:
+        */
+       memset(entry,0,sizeof(*entry));
+
+#ifdef CONFIG_INTR_REMAP
+       if (intr_remapping_enabled) {
+               struct intel_iommu *iommu = map_ioapic_to_ir(apic);
+               struct irte irte;
+               struct IR_IO_APIC_route_entry *ir_entry =
+                       (struct IR_IO_APIC_route_entry *) entry;
+               int index;
+
+               if (!iommu)
+                       panic("No mapping iommu for ioapic %d\n", apic);
+
+               index = alloc_irte(iommu, irq, 1);
+               if (index < 0)
+                       panic("Failed to allocate IRTE for ioapic %d\n", apic);
+
+               memset(&irte, 0, sizeof(irte));
+
+               irte.present = 1;
+               irte.dst_mode = INT_DEST_MODE;
+               irte.trigger_mode = trigger;
+               irte.dlvry_mode = INT_DELIVERY_MODE;
+               irte.vector = vector;
+               irte.dest_id = IRTE_DEST(destination);
+
+               modify_irte(irq, &irte);
+
+               ir_entry->index2 = (index >> 15) & 0x1;
+               ir_entry->zero = 0;
+               ir_entry->format = 1;
+               ir_entry->index = (index & 0x7fff);
+       } else
+#endif
+       {
+               entry->delivery_mode = INT_DELIVERY_MODE;
+               entry->dest_mode = INT_DEST_MODE;
+               entry->dest = destination;
        }
+
+       entry->mask = 0;                                /* enable IRQ */
+       entry->trigger = trigger;
+       entry->polarity = polarity;
+       entry->vector = vector;
+
+       /* Mask level triggered irqs.
+        * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
+        */
+       if (trigger)
+               entry->mask = 1;
+       return 0;
 }
 
 static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
@@ -875,24 +1028,15 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
                    apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector,
                    irq, trigger, polarity);
 
-       /*
-        * add it to the IO-APIC irq-routing table:
-        */
-       memset(&entry,0,sizeof(entry));
 
-       entry.delivery_mode = INT_DELIVERY_MODE;
-       entry.dest_mode = INT_DEST_MODE;
-       entry.dest = cpu_mask_to_apicid(mask);
-       entry.mask = 0;                         /* enable IRQ */
-       entry.trigger = trigger;
-       entry.polarity = polarity;
-       entry.vector = cfg->vector;
-
-       /* Mask level triggered irqs.
-        * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
-        */
-       if (trigger)
-               entry.mask = 1;
+       if (setup_ioapic_entry(mp_ioapics[apic].mp_apicid, irq, &entry,
+                              cpu_mask_to_apicid(mask), trigger, polarity,
+                              cfg->vector)) {
+               printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
+                      mp_ioapics[apic].mp_apicid, pin);
+               __clear_irq_vector(irq);
+               return;
+       }
 
        ioapic_register_intr(irq, trigger);
        if (irq < 16)
@@ -944,6 +1088,9 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
 {
        struct IO_APIC_route_entry entry;
 
+       if (intr_remapping_enabled)
+               return;
+
        memset(&entry, 0, sizeof(entry));
 
        /*
@@ -1090,6 +1237,7 @@ static __apicdebuginit void print_APIC_bitfield (int base)
 void __apicdebuginit print_local_APIC(void * dummy)
 {
        unsigned int v, ver, maxlvt;
+       unsigned long icr;
 
        if (apic_verbosity == APIC_QUIET)
                return;
@@ -1097,7 +1245,7 @@ void __apicdebuginit print_local_APIC(void * dummy)
        printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
                smp_processor_id(), hard_smp_processor_id());
        v = apic_read(APIC_ID);
-       printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(read_apic_id()));
+       printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, read_apic_id());
        v = apic_read(APIC_LVR);
        printk(KERN_INFO "... APIC VERSION: %08x\n", v);
        ver = GET_APIC_VERSION(v);
@@ -1133,10 +1281,9 @@ void __apicdebuginit print_local_APIC(void * dummy)
        v = apic_read(APIC_ESR);
        printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
 
-       v = apic_read(APIC_ICR);
-       printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
-       v = apic_read(APIC_ICR2);
-       printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);
+       icr = apic_icr_read();
+       printk(KERN_DEBUG "... APIC ICR: %08x\n", icr);
+       printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32);
 
        v = apic_read(APIC_LVTT);
        printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
@@ -1291,7 +1438,7 @@ void disable_IO_APIC(void)
                entry.dest_mode       = 0; /* Physical */
                entry.delivery_mode   = dest_ExtINT; /* ExtInt */
                entry.vector          = 0;
-               entry.dest          = GET_APIC_ID(read_apic_id());
+               entry.dest            = read_apic_id();
 
                /*
                 * Add it to the IO-APIC irq-routing table:
@@ -1397,6 +1544,147 @@ static int ioapic_retrigger_irq(unsigned int irq)
  */
 
 #ifdef CONFIG_SMP
+
+#ifdef CONFIG_INTR_REMAP
+static void ir_irq_migration(struct work_struct *work);
+
+static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration);
+
+/*
+ * Migrate the IO-APIC irq in the presence of intr-remapping.
+ *
+ * For edge triggered, irq migration is a simple atomic update(of vector
+ * and cpu destination) of IRTE and flush the hardware cache.
+ *
+ * For level triggered, we need to modify the io-apic RTE aswell with the update
+ * vector information, along with modifying IRTE with vector and destination.
+ * So irq migration for level triggered is little  bit more complex compared to
+ * edge triggered migration. But the good news is, we use the same algorithm
+ * for level triggered migration as we have today, only difference being,
+ * we now initiate the irq migration from process context instead of the
+ * interrupt context.
+ *
+ * In future, when we do a directed EOI (combined with cpu EOI broadcast
+ * suppression) to the IO-APIC, level triggered irq migration will also be
+ * as simple as edge triggered migration and we can do the irq migration
+ * with a simple atomic update to IO-APIC RTE.
+ */
+static void migrate_ioapic_irq(int irq, cpumask_t mask)
+{
+       struct irq_cfg *cfg = irq_cfg + irq;
+       struct irq_desc *desc = irq_desc + irq;
+       cpumask_t tmp, cleanup_mask;
+       struct irte irte;
+       int modify_ioapic_rte = desc->status & IRQ_LEVEL;
+       unsigned int dest;
+       unsigned long flags;
+
+       cpus_and(tmp, mask, cpu_online_map);
+       if (cpus_empty(tmp))
+               return;
+
+       if (get_irte(irq, &irte))
+               return;
+
+       if (assign_irq_vector(irq, mask))
+               return;
+
+       cpus_and(tmp, cfg->domain, mask);
+       dest = cpu_mask_to_apicid(tmp);
+
+       if (modify_ioapic_rte) {
+               spin_lock_irqsave(&ioapic_lock, flags);
+               __target_IO_APIC_irq(irq, dest, cfg->vector);
+               spin_unlock_irqrestore(&ioapic_lock, flags);
+       }
+
+       irte.vector = cfg->vector;
+       irte.dest_id = IRTE_DEST(dest);
+
+       /*
+        * Modified the IRTE and flushes the Interrupt entry cache.
+        */
+       modify_irte(irq, &irte);
+
+       if (cfg->move_in_progress) {
+               cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+               cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+               send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+               cfg->move_in_progress = 0;
+       }
+
+       irq_desc[irq].affinity = mask;
+}
+
+static int migrate_irq_remapped_level(int irq)
+{
+       int ret = -1;
+
+       mask_IO_APIC_irq(irq);
+
+       if (io_apic_level_ack_pending(irq)) {
+               /*
+                * Interrupt in progress. Migrating irq now will change the
+                * vector information in the IO-APIC RTE and that will confuse
+                * the EOI broadcast performed by cpu.
+                * So, delay the irq migration to the next instance.
+                */
+               schedule_delayed_work(&ir_migration_work, 1);
+               goto unmask;
+       }
+
+       /* everthing is clear. we have right of way */
+       migrate_ioapic_irq(irq, irq_desc[irq].pending_mask);
+
+       ret = 0;
+       irq_desc[irq].status &= ~IRQ_MOVE_PENDING;
+       cpus_clear(irq_desc[irq].pending_mask);
+
+unmask:
+       unmask_IO_APIC_irq(irq);
+       return ret;
+}
+
+static void ir_irq_migration(struct work_struct *work)
+{
+       int irq;
+
+       for (irq = 0; irq < NR_IRQS; irq++) {
+               struct irq_desc *desc = irq_desc + irq;
+               if (desc->status & IRQ_MOVE_PENDING) {
+                       unsigned long flags;
+
+                       spin_lock_irqsave(&desc->lock, flags);
+                       if (!desc->chip->set_affinity ||
+                           !(desc->status & IRQ_MOVE_PENDING)) {
+                               desc->status &= ~IRQ_MOVE_PENDING;
+                               spin_unlock_irqrestore(&desc->lock, flags);
+                               continue;
+                       }
+
+                       desc->chip->set_affinity(irq,
+                                                irq_desc[irq].pending_mask);
+                       spin_unlock_irqrestore(&desc->lock, flags);
+               }
+       }
+}
+
+/*
+ * Migrates the IRQ destination in the process context.
+ */
+static void set_ir_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
+{
+       if (irq_desc[irq].status & IRQ_LEVEL) {
+               irq_desc[irq].status |= IRQ_MOVE_PENDING;
+               irq_desc[irq].pending_mask = mask;
+               migrate_irq_remapped_level(irq);
+               return;
+       }
+
+       migrate_ioapic_irq(irq, mask);
+}
+#endif
+
 asmlinkage void smp_irq_move_cleanup_interrupt(void)
 {
        unsigned vector, me;
@@ -1453,6 +1741,17 @@ static void irq_complete_move(unsigned int irq)
 #else
 static inline void irq_complete_move(unsigned int irq) {}
 #endif
+#ifdef CONFIG_INTR_REMAP
+static void ack_x2apic_level(unsigned int irq)
+{
+       ack_x2APIC_irq();
+}
+
+static void ack_x2apic_edge(unsigned int irq)
+{
+       ack_x2APIC_irq();
+}
+#endif
 
 static void ack_apic_edge(unsigned int irq)
 {
@@ -1527,6 +1826,21 @@ static struct irq_chip ioapic_chip __read_mostly = {
        .retrigger      = ioapic_retrigger_irq,
 };
 
+#ifdef CONFIG_INTR_REMAP
+static struct irq_chip ir_ioapic_chip __read_mostly = {
+       .name           = "IR-IO-APIC",
+       .startup        = startup_ioapic_irq,
+       .mask           = mask_IO_APIC_irq,
+       .unmask         = unmask_IO_APIC_irq,
+       .ack            = ack_x2apic_edge,
+       .eoi            = ack_x2apic_level,
+#ifdef CONFIG_SMP
+       .set_affinity   = set_ir_ioapic_affinity_irq,
+#endif
+       .retrigger      = ioapic_retrigger_irq,
+};
+#endif
+
 static inline void init_IO_APIC_traps(void)
 {
        int irq;
@@ -1712,6 +2026,8 @@ static inline void __init check_timer(void)
         * 8259A.
         */
        if (pin1 == -1) {
+               if (intr_remapping_enabled)
+                       panic("BIOS bug: timer not connected to IO-APIC");
                pin1 = pin2;
                apic1 = apic2;
                no_pin1 = 1;
@@ -1738,6 +2054,8 @@ static inline void __init check_timer(void)
                                clear_IO_APIC_pin(0, pin1);
                        goto out;
                }
+               if (intr_remapping_enabled)
+                       panic("timer doesn't work through Interrupt-remapped IO-APIC");
                clear_IO_APIC_pin(apic1, pin1);
                if (!no_pin1)
                        apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
@@ -1977,6 +2295,9 @@ void destroy_irq(unsigned int irq)
 
        dynamic_irq_cleanup(irq);
 
+#ifdef CONFIG_INTR_REMAP
+       free_irte(irq);
+#endif
        spin_lock_irqsave(&vector_lock, flags);
        __clear_irq_vector(irq);
        spin_unlock_irqrestore(&vector_lock, flags);
@@ -1995,10 +2316,41 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms
 
        tmp = TARGET_CPUS;
        err = assign_irq_vector(irq, tmp);
-       if (!err) {
-               cpus_and(tmp, cfg->domain, tmp);
-               dest = cpu_mask_to_apicid(tmp);
+       if (err)
+               return err;
+
+       cpus_and(tmp, cfg->domain, tmp);
+       dest = cpu_mask_to_apicid(tmp);
+
+#ifdef CONFIG_INTR_REMAP
+       if (irq_remapped(irq)) {
+               struct irte irte;
+               int ir_index;
+               u16 sub_handle;
+
+               ir_index = map_irq_to_irte_handle(irq, &sub_handle);
+               BUG_ON(ir_index == -1);
+
+               memset (&irte, 0, sizeof(irte));
+
+               irte.present = 1;
+               irte.dst_mode = INT_DEST_MODE;
+               irte.trigger_mode = 0; /* edge */
+               irte.dlvry_mode = INT_DELIVERY_MODE;
+               irte.vector = cfg->vector;
+               irte.dest_id = IRTE_DEST(dest);
+
+               modify_irte(irq, &irte);
 
+               msg->address_hi = MSI_ADDR_BASE_HI;
+               msg->data = sub_handle;
+               msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
+                                 MSI_ADDR_IR_SHV |
+                                 MSI_ADDR_IR_INDEX1(ir_index) |
+                                 MSI_ADDR_IR_INDEX2(ir_index);
+       } else
+#endif
+       {
                msg->address_hi = MSI_ADDR_BASE_HI;
                msg->address_lo =
                        MSI_ADDR_BASE_LO |
@@ -2049,6 +2401,55 @@ static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
        write_msi_msg(irq, &msg);
        irq_desc[irq].affinity = mask;
 }
+
+#ifdef CONFIG_INTR_REMAP
+/*
+ * Migrate the MSI irq to another cpumask. This migration is
+ * done in the process context using interrupt-remapping hardware.
+ */
+static void ir_set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
+{
+       struct irq_cfg *cfg = irq_cfg + irq;
+       unsigned int dest;
+       cpumask_t tmp, cleanup_mask;
+       struct irte irte;
+
+       cpus_and(tmp, mask, cpu_online_map);
+       if (cpus_empty(tmp))
+               return;
+
+       if (get_irte(irq, &irte))
+               return;
+
+       if (assign_irq_vector(irq, mask))
+               return;
+
+       cpus_and(tmp, cfg->domain, mask);
+       dest = cpu_mask_to_apicid(tmp);
+
+       irte.vector = cfg->vector;
+       irte.dest_id = IRTE_DEST(dest);
+
+       /*
+        * atomically update the IRTE with the new destination and vector.
+        */
+       modify_irte(irq, &irte);
+
+       /*
+        * After this point, all the interrupts will start arriving
+        * at the new destination. So, time to cleanup the previous
+        * vector allocation.
+        */
+       if (cfg->move_in_progress) {
+               cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+               cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+               send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+               cfg->move_in_progress = 0;
+       }
+
+       irq_desc[irq].affinity = mask;
+}
+#endif
 #endif /* CONFIG_SMP */
 
 /*
@@ -2066,26 +2467,157 @@ static struct irq_chip msi_chip = {
        .retrigger      = ioapic_retrigger_irq,
 };
 
-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+#ifdef CONFIG_INTR_REMAP
+static struct irq_chip msi_ir_chip = {
+       .name           = "IR-PCI-MSI",
+       .unmask         = unmask_msi_irq,
+       .mask           = mask_msi_irq,
+       .ack            = ack_x2apic_edge,
+#ifdef CONFIG_SMP
+       .set_affinity   = ir_set_msi_irq_affinity,
+#endif
+       .retrigger      = ioapic_retrigger_irq,
+};
+
+/*
+ * Map the PCI dev to the corresponding remapping hardware unit
+ * and allocate 'nvec' consecutive interrupt-remapping table entries
+ * in it.
+ */
+static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
+{
+       struct intel_iommu *iommu;
+       int index;
+
+       iommu = map_dev_to_ir(dev);
+       if (!iommu) {
+               printk(KERN_ERR
+                      "Unable to map PCI %s to iommu\n", pci_name(dev));
+               return -ENOENT;
+       }
+
+       index = alloc_irte(iommu, irq, nvec);
+       if (index < 0) {
+               printk(KERN_ERR
+                      "Unable to allocate %d IRTE for PCI %s\n", nvec,
+                       pci_name(dev));
+               return -ENOSPC;
+       }
+       return index;
+}
+#endif
+
+static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
 {
+       int ret;
        struct msi_msg msg;
+
+       ret = msi_compose_msg(dev, irq, &msg);
+       if (ret < 0)
+               return ret;
+
+       set_irq_msi(irq, desc);
+       write_msi_msg(irq, &msg);
+
+#ifdef CONFIG_INTR_REMAP
+       if (irq_remapped(irq)) {
+               struct irq_desc *desc = irq_desc + irq;
+               /*
+                * irq migration in process context
+                */
+               desc->status |= IRQ_MOVE_PCNTXT;
+               set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
+       } else
+#endif
+               set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+
+       return 0;
+}
+
+int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+{
        int irq, ret;
+
        irq = create_irq();
        if (irq < 0)
                return irq;
 
-       ret = msi_compose_msg(dev, irq, &msg);
+#ifdef CONFIG_INTR_REMAP
+       if (!intr_remapping_enabled)
+               goto no_ir;
+
+       ret = msi_alloc_irte(dev, irq, 1);
+       if (ret < 0)
+               goto error;
+no_ir:
+#endif
+       ret = setup_msi_irq(dev, desc, irq);
        if (ret < 0) {
                destroy_irq(irq);
                return ret;
        }
+       return 0;
 
-       set_irq_msi(irq, desc);
-       write_msi_msg(irq, &msg);
+#ifdef CONFIG_INTR_REMAP
+error:
+       destroy_irq(irq);
+       return ret;
+#endif
+}
 
-       set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+       int irq, ret, sub_handle;
+       struct msi_desc *desc;
+#ifdef CONFIG_INTR_REMAP
+       struct intel_iommu *iommu = 0;
+       int index = 0;
+#endif
 
+       sub_handle = 0;
+       list_for_each_entry(desc, &dev->msi_list, list) {
+               irq = create_irq();
+               if (irq < 0)
+                       return irq;
+#ifdef CONFIG_INTR_REMAP
+               if (!intr_remapping_enabled)
+                       goto no_ir;
+
+               if (!sub_handle) {
+                       /*
+                        * allocate the consecutive block of IRTE's
+                        * for 'nvec'
+                        */
+                       index = msi_alloc_irte(dev, irq, nvec);
+                       if (index < 0) {
+                               ret = index;
+                               goto error;
+                       }
+               } else {
+                       iommu = map_dev_to_ir(dev);
+                       if (!iommu) {
+                               ret = -ENOENT;
+                               goto error;
+                       }
+                       /*
+                        * setup the mapping between the irq and the IRTE
+                        * base index, the sub_handle pointing to the
+                        * appropriate interrupt remap table entry.
+                        */
+                       set_irte_irq(irq, iommu, index, sub_handle);
+               }
+no_ir:
+#endif
+               ret = setup_msi_irq(dev, desc, irq);
+               if (ret < 0)
+                       goto error;
+               sub_handle++;
+       }
        return 0;
+
+error:
+       destroy_irq(irq);
+       return ret;
 }
 
 void arch_teardown_msi_irq(unsigned int irq)
@@ -2333,6 +2865,10 @@ void __init setup_ioapic_dest(void)
                                setup_IO_APIC_irq(ioapic, pin, irq,
                                                  irq_trigger(irq_entry),
                                                  irq_polarity(irq_entry));
+#ifdef CONFIG_INTR_REMAP
+                       else if (intr_remapping_enabled)
+                               set_ir_ioapic_affinity_irq(irq, TARGET_CPUS);
+#endif
                        else
                                set_ioapic_affinity_irq(irq, TARGET_CPUS);
                }
index d66914287ee12f95659d823daccdfe4b7378da01..9200a1e2752dd04846cff1205d4731a8965d4b78 100644 (file)
@@ -74,6 +74,15 @@ void __init init_ISA_irqs (void)
        }
 }
 
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = {
+       .handler = no_action,
+       .mask = CPU_MASK_NONE,
+       .name = "cascade",
+};
+
 /* Overridden in paravirt.c */
 void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
 
@@ -98,6 +107,46 @@ void __init native_init_IRQ(void)
                        set_intr_gate(vector, interrupt[i]);
        }
 
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_SMP)
+       /*
+        * IRQ0 must be given a fixed assignment and initialized,
+        * because it's used before the IO-APIC is set up.
+        */
+       set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
+
+       /*
+        * The reschedule interrupt is a CPU-to-CPU reschedule-helper
+        * IPI, driven by wakeup.
+        */
+       alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
+
+       /* IPI for invalidation */
+       alloc_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
+
+       /* IPI for generic function call */
+       alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
+
+       /* IPI for single call function */
+       set_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, call_function_single_interrupt);
+#endif
+
+#ifdef CONFIG_X86_LOCAL_APIC
+       /* self generated IPI for local APIC timer */
+       alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
+
+       /* IPI vectors for APIC spurious and error interrupts */
+       alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
+       alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+#endif
+
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_MCE_P4THERMAL)
+       /* thermal monitor LVT interrupt */
+       alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
+#endif
+
+       if (!acpi_ioapic)
+               setup_irq(2, &irq2);
+
        /* setup after call gates are initialised (usually add in
         * the architecture specific gates)
         */
index 678090508a6240996aee5eedbdd5774cc86ab629..e5d23675bb7cc9acb106e323a82724f1e5b40409 100644 (file)
@@ -397,7 +397,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
        generic_bigsmp_probe();
 #endif
 
+#ifdef CONFIG_X86_32
        setup_apic_routing();
+#endif
        if (!num_processors)
                printk(KERN_ERR "MPTABLE: no processors registered!\n");
        return num_processors;
index b8c45610b20a89a6f52f9b266d68de042d688168..2434467ddf72a9722553e880917361d699b4c1be 100644 (file)
@@ -229,6 +229,12 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
        }
 }
 
+static int __init numaq_setup_ioapic_ids(void)
+{
+       /* so can skip it */
+       return 1;
+}
+
 static struct x86_quirks numaq_x86_quirks __initdata = {
        .arch_pre_time_init     = numaq_pre_time_init,
        .arch_time_init         = NULL,
@@ -243,6 +249,7 @@ static struct x86_quirks numaq_x86_quirks __initdata = {
        .mpc_oem_bus_info       = mpc_oem_bus_info,
        .mpc_oem_pci_bus        = mpc_oem_pci_bus,
        .smp_read_mpc_oem       = smp_read_mpc_oem,
+       .setup_ioapic_ids       = numaq_setup_ioapic_ids,
 };
 
 void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
index 94da4d52d798e8490f21c59c777df72d6bba86d5..5744789a78f45ce852a28ae38e1e968e0b3727cf 100644 (file)
@@ -373,8 +373,6 @@ struct pv_cpu_ops pv_cpu_ops = {
 
 struct pv_apic_ops pv_apic_ops = {
 #ifdef CONFIG_X86_LOCAL_APIC
-       .apic_write = native_apic_write,
-       .apic_read = native_apic_read,
        .setup_boot_clock = setup_boot_APIC_clock,
        .setup_secondary_clock = setup_secondary_APIC_clock,
        .startup_ipi_hook = paravirt_nop,
index 68b48e3fbcbd92b7115ac90cb59cd9c1d3bc4054..59f07e14d0830a01a7098e337dc2ab554aa76207 100644 (file)
@@ -739,6 +739,8 @@ void __init setup_arch(char **cmdline_p)
        num_physpages = max_pfn;
 
        check_efer();
+       if (cpu_has_x2apic)
+               check_x2apic();
 
        /* How many end-of-memory variables you have, grandma! */
        /* need this before calling reserve_initrd */
index 76e305e064f96f9f7ece081665de18e7fb189e9a..0e67f72d931683413160a007d554c44a438c2c28 100644 (file)
@@ -162,9 +162,16 @@ void __init setup_per_cpu_areas(void)
                        printk(KERN_INFO
                               "cpu %d has no node %d or node-local memory\n",
                                cpu, node);
+                       if (ptr)
+                               printk(KERN_DEBUG "per cpu data for cpu%d at %016lx\n",
+                                        cpu, __pa(ptr));
                }
-               else
+               else {
                        ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
+                       if (ptr)
+                               printk(KERN_DEBUG "per cpu data for cpu%d on node%d at %016lx\n",
+                                        cpu, node, __pa(ptr));
+               }
 #endif
                per_cpu_offset(cpu) = ptr - __per_cpu_start;
                memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
index 02b02583f5b5c08d3d0e33c82f5634ebfb9de4b2..2f14640500599f091720ab69ec61d44c072a7ebc 100644 (file)
@@ -105,7 +105,16 @@ static inline int restore_i387(struct _fpstate __user *buf)
                clts();
                task_thread_info(current)->status |= TS_USEDFPU;
        }
-       return restore_fpu_checking((__force struct i387_fxsave_struct *)buf);
+       err = restore_fpu_checking((__force struct i387_fxsave_struct *)buf);
+       if (unlikely(err)) {
+               /*
+                * Encountered an error while doing the restore from the
+                * user buffer, clear the fpu state.
+                */
+               clear_fpu(tsk);
+               clear_used_math();
+       }
+       return err;
 }
 
 /*
index 6112c3632345fda743e94da3c26b78798ecf29b7..0133a952d11f6163d1652113a4b57c2c8dc48f8b 100644 (file)
@@ -123,7 +123,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
 
 static atomic_t init_deasserted;
 
-static int boot_cpu_logical_apicid;
 
 /* representing cpus for which sibling maps can be computed */
 static cpumask_t cpu_sibling_setup_map;
@@ -165,6 +164,8 @@ static void unmap_cpu_to_node(int cpu)
 #endif
 
 #ifdef CONFIG_X86_32
+static int boot_cpu_logical_apicid;
+
 u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly =
                                        { [0 ... NR_CPUS-1] = BAD_APICID };
 
@@ -210,7 +211,7 @@ static void __cpuinit smp_callin(void)
        /*
         * (This works even if the APIC is not enabled.)
         */
-       phys_id = GET_APIC_ID(read_apic_id());
+       phys_id = read_apic_id();
        cpuid = smp_processor_id();
        if (cpu_isset(cpuid, cpu_callin_map)) {
                panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__,
@@ -550,8 +551,7 @@ static inline void __inquire_remote_apic(int apicid)
                        printk(KERN_CONT
                               "a previous APIC delivery may have failed\n");
 
-               apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
-               apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
+               apic_icr_write(APIC_DM_REMRD | regs[i], apicid);
 
                timeout = 0;
                do {
@@ -583,11 +583,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
        int maxlvt;
 
        /* Target chip */
-       apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
-
        /* Boot on the stack */
        /* Kick the second */
-       apic_write(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
+       apic_icr_write(APIC_DM_NMI | APIC_DEST_LOGICAL, logical_apicid);
 
        pr_debug("Waiting for send to finish...\n");
        send_status = safe_apic_wait_icr_idle();
@@ -640,13 +638,11 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
        /*
         * Turn INIT on target chip
         */
-       apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
-
        /*
         * Send IPI
         */
-       apic_write(APIC_ICR,
-                  APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);
+       apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT,
+                      phys_apicid);
 
        pr_debug("Waiting for send to finish...\n");
        send_status = safe_apic_wait_icr_idle();
@@ -656,10 +652,8 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
        pr_debug("Deasserting INIT.\n");
 
        /* Target chip */
-       apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
-
        /* Send IPI */
-       apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+       apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid);
 
        pr_debug("Waiting for send to finish...\n");
        send_status = safe_apic_wait_icr_idle();
@@ -702,11 +696,10 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
                 */
 
                /* Target chip */
-               apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
-
                /* Boot on the stack */
                /* Kick the second */
-               apic_write(APIC_ICR, APIC_DM_STARTUP | (start_eip >> 12));
+               apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12),
+                              phys_apicid);
 
                /*
                 * Give the other CPU some time to accept the IPI.
@@ -1150,10 +1143,17 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
         * Setup boot CPU information
         */
        smp_store_cpu_info(0); /* Final full version of the data */
+#ifdef CONFIG_X86_32
        boot_cpu_logical_apicid = logical_smp_processor_id();
+#endif
        current_thread_info()->cpu = 0;  /* needed? */
        set_cpu_sibling_map(0);
 
+#ifdef CONFIG_X86_64
+       enable_IR_x2apic();
+       setup_apic_routing();
+#endif
+
        if (smp_sanity_check(max_cpus) < 0) {
                printk(KERN_INFO "SMP disabled\n");
                disable_smp();
@@ -1161,9 +1161,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
        }
 
        preempt_disable();
-       if (GET_APIC_ID(read_apic_id()) != boot_cpu_physical_apicid) {
+       if (read_apic_id() != boot_cpu_physical_apicid) {
                panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
-                    GET_APIC_ID(read_apic_id()), boot_cpu_physical_apicid);
+                    read_apic_id(), boot_cpu_physical_apicid);
                /* Or can we switch back to PIC here? */
        }
        preempt_enable();
index d67ce5f044ba342a327ba634a17ccea09698e040..7b987852e8761cf6ae4156f61177a7c6863cb0f7 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/init.h>
 #include <asm/io.h>
 #include <asm/bios_ebda.h>
-#include <asm/mach-summit/mach_mpparse.h>
+#include <asm/summit/mpparse.h>
 
 static struct rio_table_hdr *rio_table_hdr __initdata;
 static struct scal_detail   *scal_devs[MAX_NUMNODES] __initdata;
index 170d43c174878ac14b15185affa0a60599e290e2..3d1be4f0fac563f56247204e8d62967872092268 100644 (file)
@@ -8,12 +8,12 @@
 #define __NO_STUBS
 
 #define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
-#undef _ASM_X86_64_UNISTD_H_
+#undef ASM_X86__UNISTD_64_H
 #include <asm/unistd_64.h>
 
 #undef __SYSCALL
 #define __SYSCALL(nr, sym) [nr] = sym,
-#undef _ASM_X86_64_UNISTD_H_
+#undef ASM_X86__UNISTD_64_H
 
 typedef void (*sys_call_ptr_t)(void);
 
index 3f18d73f420c414d809a1046dd5676b992e8676e..513caaca7115eecf5d7a58de7cf12fbe9e60e6e4 100644 (file)
@@ -1131,7 +1131,14 @@ asmlinkage void math_state_restore(void)
        }
 
        clts();                         /* Allow maths ops (or we recurse) */
-       restore_fpu_checking(&me->thread.xstate->fxsave);
+       /*
+        * Paranoid restore. send a SIGSEGV if we fail to restore the state.
+        */
+       if (unlikely(restore_fpu_checking(&me->thread.xstate->fxsave))) {
+               stts();
+               force_sig(SIGSEGV, me);
+               return;
+       }
        task_thread_info(me)->status |= TS_USEDFPU;
        me->fpu_counter++;
 }
index 6ca515d6db543b9a7739b9f2f9ab39d181ed3f9b..61531d5c9507e2ce3eea7e177c2e1a7a985cda27 100644 (file)
@@ -905,8 +905,8 @@ static inline int __init activate_vmi(void)
 #endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
-       para_fill(pv_apic_ops.apic_read, APICRead);
-       para_fill(pv_apic_ops.apic_write, APICWrite);
+       para_fill(apic_ops->read, APICRead);
+       para_fill(apic_ops->write, APICWrite);
 #endif
 
        /*
index d9249a882aa5b0c2204fc16724e0848e8184d543..65f0b8a47bed0dd2ccdd31e507cdfd70846c4d48 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/lguest_launcher.h>
 #include <linux/virtio_console.h>
 #include <linux/pm.h>
+#include <asm/apic.h>
 #include <asm/lguest.h>
 #include <asm/paravirt.h>
 #include <asm/param.h>
@@ -783,14 +784,44 @@ static void lguest_wbinvd(void)
  * code qualifies for Advanced.  It will also never interrupt anything.  It
  * does, however, allow us to get through the Linux boot code. */
 #ifdef CONFIG_X86_LOCAL_APIC
-static void lguest_apic_write(unsigned long reg, u32 v)
+static void lguest_apic_write(u32 reg, u32 v)
 {
 }
 
-static u32 lguest_apic_read(unsigned long reg)
+static u32 lguest_apic_read(u32 reg)
 {
        return 0;
 }
+
+static u64 lguest_apic_icr_read(void)
+{
+       return 0;
+}
+
+static void lguest_apic_icr_write(u32 low, u32 id)
+{
+       /* Warn to see if there's any stray references */
+       WARN_ON(1);
+}
+
+static void lguest_apic_wait_icr_idle(void)
+{
+       return;
+}
+
+static u32 lguest_apic_safe_wait_icr_idle(void)
+{
+       return 0;
+}
+
+static struct apic_ops lguest_basic_apic_ops = {
+       .read = lguest_apic_read,
+       .write = lguest_apic_write,
+       .icr_read = lguest_apic_icr_read,
+       .icr_write = lguest_apic_icr_write,
+       .wait_icr_idle = lguest_apic_wait_icr_idle,
+       .safe_wait_icr_idle = lguest_apic_safe_wait_icr_idle,
+};
 #endif
 
 /* STOP!  Until an interrupt comes in. */
@@ -990,8 +1021,7 @@ __init void lguest_init(void)
 
 #ifdef CONFIG_X86_LOCAL_APIC
        /* apic read/write intercepts */
-       pv_apic_ops.apic_write = lguest_apic_write;
-       pv_apic_ops.apic_read = lguest_apic_read;
+       apic_ops = &lguest_basic_apic_ops;
 #endif
 
        /* time operations */
index 3f2cf11f201aaf78ca5999e20d230e36d762ffdd..37b9ae4d44c5b755470cb3661328b073e951b068 100644 (file)
@@ -38,15 +38,6 @@ void __init pre_intr_init_hook(void)
        init_ISA_irqs();
 }
 
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq2 = {
-       .handler = no_action,
-       .mask = CPU_MASK_NONE,
-       .name = "cascade",
-};
-
 /**
  * intr_init_hook - post gate setup interrupt initialisation
  *
@@ -62,12 +53,6 @@ void __init intr_init_hook(void)
                if (x86_quirks->arch_intr_init())
                        return;
        }
-#ifdef CONFIG_X86_LOCAL_APIC
-       apic_intr_init();
-#endif
-
-       if (!acpi_ioapic)
-               setup_irq(2, &irq2);
 }
 
 /**
index 0dbd7803a1d5e4199f6d1c84676296247428a2d3..4706de7676b188a185e48cb34a0c40eaf9a7e310 100644 (file)
@@ -9,4 +9,4 @@ obj-$(CONFIG_X86_NUMAQ)         += numaq.o
 obj-$(CONFIG_X86_SUMMIT)       += summit.o
 obj-$(CONFIG_X86_BIGSMP)       += bigsmp.o
 obj-$(CONFIG_X86_ES7000)       += es7000.o
-obj-$(CONFIG_X86_ES7000)       += ../../x86/mach-es7000/
+obj-$(CONFIG_X86_ES7000)       += ../../x86/es7000/
index 59d7717145590b4f70f7e75daad74bff953d8b3a..df37fc9d6a2612d0ddf1105b8510a320b3445923 100644 (file)
@@ -5,18 +5,17 @@
 #define APIC_DEFINITION 1
 #include <linux/threads.h>
 #include <linux/cpumask.h>
-#include <asm/smp.h>
 #include <asm/mpspec.h>
 #include <asm/genapic.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
 #include <linux/kernel.h>
-#include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/dmi.h>
-#include <asm/mach-bigsmp/mach_apic.h>
-#include <asm/mach-bigsmp/mach_apicdef.h>
-#include <asm/mach-bigsmp/mach_ipi.h>
+#include <asm/bigsmp/apicdef.h>
+#include <linux/smp.h>
+#include <asm/bigsmp/apic.h>
+#include <asm/bigsmp/ipi.h>
 #include <asm/mach-default/mach_mpparse.h>
 
 static int dmi_bigsmp; /* can be set by dmi scanners */
index 4742626f08c4c7abb5f815248c541d03362b602f..520cca0ee04e382227acb882ebd3a0665a5135b8 100644 (file)
@@ -4,20 +4,19 @@
 #define APIC_DEFINITION 1
 #include <linux/threads.h>
 #include <linux/cpumask.h>
-#include <asm/smp.h>
 #include <asm/mpspec.h>
 #include <asm/genapic.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/smp.h>
 #include <linux/init.h>
-#include <asm/mach-es7000/mach_apicdef.h>
-#include <asm/mach-es7000/mach_apic.h>
-#include <asm/mach-es7000/mach_ipi.h>
-#include <asm/mach-es7000/mach_mpparse.h>
-#include <asm/mach-es7000/mach_wakecpu.h>
+#include <asm/es7000/apicdef.h>
+#include <linux/smp.h>
+#include <asm/es7000/apic.h>
+#include <asm/es7000/ipi.h>
+#include <asm/es7000/mpparse.h>
+#include <asm/es7000/wakecpu.h>
 
 static int probe_es7000(void)
 {
index 8091e68764c4b623b4f4523cc4bb9324630f9f20..8cf58394975e199ac7aaa0f70c2bc0de6547ccf2 100644 (file)
@@ -4,7 +4,6 @@
 #define APIC_DEFINITION 1
 #include <linux/threads.h>
 #include <linux/cpumask.h>
-#include <linux/smp.h>
 #include <asm/mpspec.h>
 #include <asm/genapic.h>
 #include <asm/fixmap.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <asm/mach-numaq/mach_apic.h>
-#include <asm/mach-numaq/mach_apicdef.h>
-#include <asm/mach-numaq/mach_ipi.h>
-#include <asm/mach-numaq/mach_mpparse.h>
-#include <asm/mach-numaq/mach_wakecpu.h>
+#include <asm/numaq/apicdef.h>
+#include <linux/smp.h>
+#include <asm/numaq/apic.h>
+#include <asm/numaq/ipi.h>
+#include <asm/numaq/mpparse.h>
+#include <asm/numaq/wakecpu.h>
 #include <asm/numaq.h>
 
 static int mps_oem_check(struct mp_config_table *mpc, char *oem,
index a97ea0f35b1ee821a96d101d27eb50f6f6e7faef..6ad6b67a723de01768c0373cac3023a43cd289b3 100644 (file)
@@ -4,19 +4,18 @@
 #define APIC_DEFINITION 1
 #include <linux/threads.h>
 #include <linux/cpumask.h>
-#include <asm/smp.h>
 #include <asm/mpspec.h>
 #include <asm/genapic.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/smp.h>
 #include <linux/init.h>
-#include <asm/mach-summit/mach_apic.h>
-#include <asm/mach-summit/mach_apicdef.h>
-#include <asm/mach-summit/mach_ipi.h>
-#include <asm/mach-summit/mach_mpparse.h>
+#include <asm/summit/apicdef.h>
+#include <linux/smp.h>
+#include <asm/summit/apic.h>
+#include <asm/summit/ipi.h>
+#include <asm/summit/mpparse.h>
 
 static int probe_summit(void)
 {
index 9ff6e3cbf08feaf41c36d9a48c46ae45a105174e..8d28925ebed97345f6acd76cff6313be69f67d08 100644 (file)
@@ -36,6 +36,7 @@
 #include <xen/hvc-console.h>
 
 #include <asm/paravirt.h>
+#include <asm/apic.h>
 #include <asm/page.h>
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
@@ -580,16 +581,47 @@ static void xen_io_delay(void)
 }
 
 #ifdef CONFIG_X86_LOCAL_APIC
-static u32 xen_apic_read(unsigned long reg)
+static u32 xen_apic_read(u32 reg)
 {
        return 0;
 }
 
-static void xen_apic_write(unsigned long reg, u32 val)
+static void xen_apic_write(u32 reg, u32 val)
 {
        /* Warn to see if there's any stray references */
        WARN_ON(1);
 }
+
+static u64 xen_apic_icr_read(void)
+{
+       return 0;
+}
+
+static void xen_apic_icr_write(u32 low, u32 id)
+{
+       /* Warn to see if there's any stray references */
+       WARN_ON(1);
+}
+
+static void xen_apic_wait_icr_idle(void)
+{
+        return;
+}
+
+static u32 xen_safe_apic_wait_icr_idle(void)
+{
+        return 0;
+}
+
+static struct apic_ops xen_basic_apic_ops = {
+       .read = xen_apic_read,
+       .write = xen_apic_write,
+       .icr_read = xen_apic_icr_read,
+       .icr_write = xen_apic_icr_write,
+       .wait_icr_idle = xen_apic_wait_icr_idle,
+       .safe_wait_icr_idle = xen_safe_apic_wait_icr_idle,
+};
+
 #endif
 
 static void xen_flush_tlb(void)
@@ -1273,8 +1305,6 @@ static const struct pv_irq_ops xen_irq_ops __initdata = {
 
 static const struct pv_apic_ops xen_apic_ops __initdata = {
 #ifdef CONFIG_X86_LOCAL_APIC
-       .apic_write = xen_apic_write,
-       .apic_read = xen_apic_read,
        .setup_boot_clock = paravirt_nop,
        .setup_secondary_clock = paravirt_nop,
        .startup_ipi_hook = paravirt_nop,
@@ -1677,6 +1707,13 @@ asmlinkage void __init xen_start_kernel(void)
        pv_apic_ops = xen_apic_ops;
        pv_mmu_ops = xen_mmu_ops;
 
+#ifdef CONFIG_X86_LOCAL_APIC
+       /*
+        * set up the basic apic ops.
+        */
+       apic_ops = &xen_basic_apic_ops;
+#endif
+
        if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) {
                pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start;
                pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit;
index ac0919460d143c9e45b10212899d3b2cc3ec3a25..5d3f1303da985417d0ab192c5909aadd5f60ab0b 100644 (file)
@@ -225,7 +225,7 @@ int crypto_init_digest_ops_async(struct crypto_tfm *tfm)
        struct ahash_tfm  *crt  = &tfm->crt_ahash;
        struct digest_alg *dalg = &tfm->__crt_alg->cra_digest;
 
-       if (dalg->dia_digestsize > crypto_tfm_alg_blocksize(tfm))
+       if (dalg->dia_digestsize > PAGE_SIZE / 8)
                return -EINVAL;
 
        crt->init       = digest_async_init;
index 59821a22d75238e568fc07dff1b1d6e73f804640..66368022e0bf32466fa4a4e0569e9e03303b6b12 100644 (file)
@@ -481,21 +481,31 @@ next_one:
 
                        for (k = 0, temp = 0; k < template[i].np; k++) {
                                printk(KERN_INFO "page %u\n", k);
-                               q = &axbuf[IDX[k]];
-                               hexdump(q, template[i].tap[k]);
+                               q = &xbuf[IDX[k]];
+
+                               n = template[i].tap[k];
+                               if (k == template[i].np - 1)
+                                       n += enc ? authsize : -authsize;
+                               hexdump(q, n);
                                printk(KERN_INFO "%s\n",
-                                      memcmp(q, template[i].result + temp,
-                                             template[i].tap[k] -
-                                             (k < template[i].np - 1 || enc ?
-                                              0 : authsize)) ?
+                                      memcmp(q, template[i].result + temp, n) ?
                                       "fail" : "pass");
 
-                               for (n = 0; q[template[i].tap[k] + n]; n++)
-                                       ;
+                               q += n;
+                               if (k == template[i].np - 1 && !enc) {
+                                       if (memcmp(q, template[i].input +
+                                                     temp + n, authsize))
+                                               n = authsize;
+                                       else
+                                               n = 0;
+                               } else {
+                                       for (n = 0; q[n]; n++)
+                                               ;
+                               }
                                if (n) {
                                        printk("Result buffer corruption %u "
                                               "bytes:\n", n);
-                                       hexdump(&q[template[i].tap[k]], n);
+                                       hexdump(q, n);
                                }
 
                                temp += template[i].tap[k];
index a280ab3d0833fa29e8ae031bbb53bfdba37c4191..2735bde73475c5f840c2d52266fd47e54b730bcd 100644 (file)
@@ -57,6 +57,7 @@ obj-$(CONFIG_ATA_OVER_ETH)    += block/aoe/
 obj-$(CONFIG_PARIDE)           += block/paride/
 obj-$(CONFIG_TC)               += tc/
 obj-$(CONFIG_USB)              += usb/
+obj-$(CONFIG_USB_MUSB_HDRC)    += usb/musb/
 obj-$(CONFIG_PCI)              += usb/
 obj-$(CONFIG_USB_GADGET)       += usb/gadget/
 obj-$(CONFIG_SERIO)            += input/serio/
index f7feae4ebb5e9981e7f730f637a2b1e54f5cc767..128202e18fc98780b2f576ed20e221dd75d3fe41 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/io.h>
 #include <asm/msr.h>
 #include <asm/cpufeature.h>
+#include <asm/i387.h>
 
 
 #define PFX    KBUILD_MODNAME ": "
@@ -67,16 +68,23 @@ enum {
  * Another possible performance boost may come from simply buffering
  * until we have 4 bytes, thus returning a u32 at a time,
  * instead of the current u8-at-a-time.
+ *
+ * Padlock instructions can generate a spurious DNA fault, so
+ * we have to call them in the context of irq_ts_save/restore()
  */
 
 static inline u32 xstore(u32 *addr, u32 edx_in)
 {
        u32 eax_out;
+       int ts_state;
+
+       ts_state = irq_ts_save();
 
        asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
                :"=m"(*addr), "=a"(eax_out)
                :"D"(addr), "d"(edx_in));
 
+       irq_ts_restore(ts_state);
        return eax_out;
 }
 
index 54a2a166e566740f1ebae141495e09013015aeea..bf2917d197a018d13f1bc48ad4c93c0b0a93ccde 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <asm/byteorder.h>
+#include <asm/i387.h>
 #include "padlock.h"
 
 /* Control word. */
@@ -141,6 +142,12 @@ static inline void padlock_reset_key(void)
        asm volatile ("pushfl; popfl");
 }
 
+/*
+ * While the padlock instructions don't use FP/SSE registers, they
+ * generate a spurious DNA fault when cr0.ts is '1'. These instructions
+ * should be used only inside the irq_ts_save/restore() context
+ */
+
 static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key,
                                  void *control_word)
 {
@@ -205,15 +212,23 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
 static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
        struct aes_ctx *ctx = aes_ctx(tfm);
+       int ts_state;
        padlock_reset_key();
+
+       ts_state = irq_ts_save();
        aes_crypt(in, out, ctx->E, &ctx->cword.encrypt);
+       irq_ts_restore(ts_state);
 }
 
 static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
        struct aes_ctx *ctx = aes_ctx(tfm);
+       int ts_state;
        padlock_reset_key();
+
+       ts_state = irq_ts_save();
        aes_crypt(in, out, ctx->D, &ctx->cword.decrypt);
+       irq_ts_restore(ts_state);
 }
 
 static struct crypto_alg aes_alg = {
@@ -244,12 +259,14 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc,
        struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
        struct blkcipher_walk walk;
        int err;
+       int ts_state;
 
        padlock_reset_key();
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
        err = blkcipher_walk_virt(desc, &walk);
 
+       ts_state = irq_ts_save();
        while ((nbytes = walk.nbytes)) {
                padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr,
                                   ctx->E, &ctx->cword.encrypt,
@@ -257,6 +274,7 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc,
                nbytes &= AES_BLOCK_SIZE - 1;
                err = blkcipher_walk_done(desc, &walk, nbytes);
        }
+       irq_ts_restore(ts_state);
 
        return err;
 }
@@ -268,12 +286,14 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc,
        struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
        struct blkcipher_walk walk;
        int err;
+       int ts_state;
 
        padlock_reset_key();
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
        err = blkcipher_walk_virt(desc, &walk);
 
+       ts_state = irq_ts_save();
        while ((nbytes = walk.nbytes)) {
                padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr,
                                   ctx->D, &ctx->cword.decrypt,
@@ -281,7 +301,7 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc,
                nbytes &= AES_BLOCK_SIZE - 1;
                err = blkcipher_walk_done(desc, &walk, nbytes);
        }
-
+       irq_ts_restore(ts_state);
        return err;
 }
 
@@ -314,12 +334,14 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc,
        struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
        struct blkcipher_walk walk;
        int err;
+       int ts_state;
 
        padlock_reset_key();
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
        err = blkcipher_walk_virt(desc, &walk);
 
+       ts_state = irq_ts_save();
        while ((nbytes = walk.nbytes)) {
                u8 *iv = padlock_xcrypt_cbc(walk.src.virt.addr,
                                            walk.dst.virt.addr, ctx->E,
@@ -329,6 +351,7 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc,
                nbytes &= AES_BLOCK_SIZE - 1;
                err = blkcipher_walk_done(desc, &walk, nbytes);
        }
+       irq_ts_restore(ts_state);
 
        return err;
 }
@@ -340,12 +363,14 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc,
        struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
        struct blkcipher_walk walk;
        int err;
+       int ts_state;
 
        padlock_reset_key();
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
        err = blkcipher_walk_virt(desc, &walk);
 
+       ts_state = irq_ts_save();
        while ((nbytes = walk.nbytes)) {
                padlock_xcrypt_cbc(walk.src.virt.addr, walk.dst.virt.addr,
                                   ctx->D, walk.iv, &ctx->cword.decrypt,
@@ -354,6 +379,7 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc,
                err = blkcipher_walk_done(desc, &walk, nbytes);
        }
 
+       irq_ts_restore(ts_state);
        return err;
 }
 
index 40d5680fa0139c926ab500545736a3ac9abd0035..a7fbadebf62330864734e5302be660d2f39ab51a 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/scatterlist.h>
+#include <asm/i387.h>
 #include "padlock.h"
 
 #define SHA1_DEFAULT_FALLBACK  "sha1-generic"
@@ -102,6 +103,7 @@ static void padlock_do_sha1(const char *in, char *out, int count)
         *     PadLock microcode needs it that big. */
        char buf[128+16];
        char *result = NEAREST_ALIGNED(buf);
+       int ts_state;
 
        ((uint32_t *)result)[0] = SHA1_H0;
        ((uint32_t *)result)[1] = SHA1_H1;
@@ -109,9 +111,12 @@ static void padlock_do_sha1(const char *in, char *out, int count)
        ((uint32_t *)result)[3] = SHA1_H3;
        ((uint32_t *)result)[4] = SHA1_H4;
  
+       /* prevent taking the spurious DNA fault with padlock. */
+       ts_state = irq_ts_save();
        asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" /* rep xsha1 */
                      : "+S"(in), "+D"(result)
                      : "c"(count), "a"(0));
+       irq_ts_restore(ts_state);
 
        padlock_output_block((uint32_t *)result, (uint32_t *)out, 5);
 }
@@ -123,6 +128,7 @@ static void padlock_do_sha256(const char *in, char *out, int count)
         *     PadLock microcode needs it that big. */
        char buf[128+16];
        char *result = NEAREST_ALIGNED(buf);
+       int ts_state;
 
        ((uint32_t *)result)[0] = SHA256_H0;
        ((uint32_t *)result)[1] = SHA256_H1;
@@ -133,9 +139,12 @@ static void padlock_do_sha256(const char *in, char *out, int count)
        ((uint32_t *)result)[6] = SHA256_H6;
        ((uint32_t *)result)[7] = SHA256_H7;
 
+       /* prevent taking the spurious DNA fault with padlock. */
+       ts_state = irq_ts_save();
        asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" /* rep xsha256 */
                      : "+S"(in), "+D"(result)
                      : "c"(count), "a"(0));
+       irq_ts_restore(ts_state);
 
        padlock_output_block((uint32_t *)result, (uint32_t *)out, 8);
 }
index 681c15f420834a545292b17974e523d387d2f243..ee827a7f7c6a48257e5af20219dcb256421d8994 100644 (file)
@@ -96,6 +96,9 @@ struct talitos_private {
        unsigned int exec_units;
        unsigned int desc_types;
 
+       /* SEC Compatibility info */
+       unsigned long features;
+
        /* next channel to be assigned next incoming descriptor */
        atomic_t last_chan;
 
@@ -133,6 +136,9 @@ struct talitos_private {
        struct hwrng rng;
 };
 
+/* .features flag */
+#define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001
+
 /*
  * map virtual single (contiguous) pointer to h/w descriptor pointer
  */
@@ -785,7 +791,7 @@ static void ipsec_esp_encrypt_done(struct device *dev,
        /* copy the generated ICV to dst */
        if (edesc->dma_len) {
                icvdata = &edesc->link_tbl[edesc->src_nents +
-                                          edesc->dst_nents + 1];
+                                          edesc->dst_nents + 2];
                sg = sg_last(areq->dst, edesc->dst_nents);
                memcpy((char *)sg_virt(sg) + sg->length - ctx->authsize,
                       icvdata, ctx->authsize);
@@ -814,7 +820,7 @@ static void ipsec_esp_decrypt_done(struct device *dev,
                /* auth check */
                if (edesc->dma_len)
                        icvdata = &edesc->link_tbl[edesc->src_nents +
-                                                  edesc->dst_nents + 1];
+                                                  edesc->dst_nents + 2];
                else
                        icvdata = &edesc->link_tbl[0];
 
@@ -921,10 +927,30 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
                sg_count = sg_to_link_tbl(areq->src, sg_count, cryptlen,
                                          &edesc->link_tbl[0]);
                if (sg_count > 1) {
+                       struct talitos_ptr *link_tbl_ptr =
+                               &edesc->link_tbl[sg_count-1];
+                       struct scatterlist *sg;
+                       struct talitos_private *priv = dev_get_drvdata(dev);
+
                        desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
                        desc->ptr[4].ptr = cpu_to_be32(edesc->dma_link_tbl);
                        dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
                                                   edesc->dma_len, DMA_BIDIRECTIONAL);
+                       /* If necessary for this SEC revision,
+                        * add a link table entry for ICV.
+                        */
+                       if ((priv->features &
+                            TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT) &&
+                           (edesc->desc.hdr & DESC_HDR_MODE0_ENCRYPT) == 0) {
+                               link_tbl_ptr->j_extent = 0;
+                               link_tbl_ptr++;
+                               link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
+                               link_tbl_ptr->len = cpu_to_be16(authsize);
+                               sg = sg_last(areq->src, edesc->src_nents ? : 1);
+                               link_tbl_ptr->ptr = cpu_to_be32(
+                                               (char *)sg_dma_address(sg)
+                                               + sg->length - authsize);
+                       }
                } else {
                        /* Only one segment now, so no link tbl needed */
                        desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src));
@@ -944,12 +970,11 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
                desc->ptr[5].ptr = cpu_to_be32(sg_dma_address(areq->dst));
        } else {
                struct talitos_ptr *link_tbl_ptr =
-                       &edesc->link_tbl[edesc->src_nents];
-               struct scatterlist *sg;
+                       &edesc->link_tbl[edesc->src_nents + 1];
 
                desc->ptr[5].ptr = cpu_to_be32((struct talitos_ptr *)
                                               edesc->dma_link_tbl +
-                                              edesc->src_nents);
+                                              edesc->src_nents + 1);
                if (areq->src == areq->dst) {
                        memcpy(link_tbl_ptr, &edesc->link_tbl[0],
                               edesc->src_nents * sizeof(struct talitos_ptr));
@@ -957,14 +982,10 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
                        sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen,
                                                  link_tbl_ptr);
                }
+               /* Add an entry to the link table for ICV data */
                link_tbl_ptr += sg_count - 1;
-
-               /* handle case where sg_last contains the ICV exclusively */
-               sg = sg_last(areq->dst, edesc->dst_nents);
-               if (sg->length == ctx->authsize)
-                       link_tbl_ptr--;
-
                link_tbl_ptr->j_extent = 0;
+               sg_count++;
                link_tbl_ptr++;
                link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
                link_tbl_ptr->len = cpu_to_be16(authsize);
@@ -973,7 +994,7 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
                link_tbl_ptr->ptr = cpu_to_be32((struct talitos_ptr *)
                                                edesc->dma_link_tbl +
                                                edesc->src_nents +
-                                               edesc->dst_nents + 1);
+                                               edesc->dst_nents + 2);
 
                desc->ptr[5].j_extent |= DESC_PTR_LNKTBL_JUMP;
                dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
@@ -1040,12 +1061,12 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
 
        /*
         * allocate space for base edesc plus the link tables,
-        * allowing for a separate entry for the generated ICV (+ 1),
+        * allowing for two separate entries for ICV and generated ICV (+ 2),
         * and the ICV data itself
         */
        alloc_len = sizeof(struct ipsec_esp_edesc);
        if (src_nents || dst_nents) {
-               dma_len = (src_nents + dst_nents + 1) *
+               dma_len = (src_nents + dst_nents + 2) *
                                 sizeof(struct talitos_ptr) + ctx->authsize;
                alloc_len += dma_len;
        } else {
@@ -1104,7 +1125,7 @@ static int aead_authenc_decrypt(struct aead_request *req)
        /* stash incoming ICV for later cmp with ICV generated by the h/w */
        if (edesc->dma_len)
                icvdata = &edesc->link_tbl[edesc->src_nents +
-                                          edesc->dst_nents + 1];
+                                          edesc->dst_nents + 2];
        else
                icvdata = &edesc->link_tbl[0];
 
@@ -1480,6 +1501,9 @@ static int talitos_probe(struct of_device *ofdev,
                goto err_out;
        }
 
+       if (of_device_is_compatible(np, "fsl,sec3.0"))
+               priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
+
        priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels,
                                  GFP_KERNEL);
        priv->tail_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels,
index 18355ae2155d9bf83d9276ac5204dfecf01a40b1..4655b794ebe3c7d06ad911cf898c25a5061b03d0 100644 (file)
@@ -1593,7 +1593,7 @@ fail1:
        if (machine_is_omap_h2()) {
                /* full speed signaling by default */
                isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
-                       MC1_SPEED_REG);
+                       MC1_SPEED);
                isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2,
                        MC2_SPD_SUSP_CTRL);
 
index 66bafe308b0cd053252e4f0cbf8b3644dfd7c5a5..692a79ec2a22327e98c94ef4946fe2f69b6747da 100644 (file)
@@ -1,10 +1,11 @@
 #ifndef _I8042_SPARCIO_H
 #define _I8042_SPARCIO_H
 
+#include <linux/of_device.h>
+
 #include <asm/io.h>
 #include <asm/oplib.h>
 #include <asm/prom.h>
-#include <asm/of_device.h>
 
 static int i8042_kbd_irq = -1;
 static int i8042_aux_irq = -1;
index 4bf4f7b205f24a62d3ed8fefcbc7cbdb443cc197..b468f904c7f88591cd952c983c44693412d7b239 100644 (file)
 #define DP(__mask, __fmt, __args...) do { \
        if (bp->msglevel & (__mask)) \
                printk(DP_LEVEL "[%s:%d(%s)]" __fmt, __func__, __LINE__, \
-                       bp->dev?(bp->dev->name):"?", ##__args); \
+                       bp->dev ? (bp->dev->name) : "?", ##__args); \
        } while (0)
 
 /* errors debug print */
 #define BNX2X_DBG_ERR(__fmt, __args...) do { \
        if (bp->msglevel & NETIF_MSG_PROBE) \
                printk(KERN_ERR "[%s:%d(%s)]" __fmt, __func__, __LINE__, \
-                       bp->dev?(bp->dev->name):"?", ##__args); \
+                       bp->dev ? (bp->dev->name) : "?", ##__args); \
        } while (0)
 
 /* for errors (never masked) */
 #define BNX2X_ERR(__fmt, __args...) do { \
        printk(KERN_ERR "[%s:%d(%s)]" __fmt, __func__, __LINE__, \
-               bp->dev?(bp->dev->name):"?", ##__args); \
+               bp->dev ? (bp->dev->name) : "?", ##__args); \
        } while (0)
 
 /* before we have a dev->name use dev_info() */
 #define SHMEM_RD(bp, field)            REG_RD(bp, SHMEM_ADDR(bp, field))
 #define SHMEM_WR(bp, field, val)       REG_WR(bp, SHMEM_ADDR(bp, field), val)
 
-#define NIG_WR(reg, val)       REG_WR(bp, reg, val)
-#define EMAC_WR(reg, val)      REG_WR(bp, emac_base + reg, val)
-#define BMAC_WR(reg, val)      REG_WR(bp, GRCBASE_NIG + bmac_addr + reg, val)
-
-
-#define for_each_queue(bp, var)        for (var = 0; var < bp->num_queues; var++)
-
-#define for_each_nondefault_queue(bp, var) \
-                               for (var = 1; var < bp->num_queues; var++)
-#define is_multi(bp)           (bp->num_queues > 1)
+#define EMAC_RD(bp, reg)               REG_RD(bp, emac_base + reg)
+#define EMAC_WR(bp, reg, val)          REG_WR(bp, emac_base + reg, val)
 
 
 /* fast path */
@@ -163,7 +155,7 @@ struct sw_rx_page {
 #define NUM_RX_SGE_PAGES               2
 #define RX_SGE_CNT             (BCM_PAGE_SIZE / sizeof(struct eth_rx_sge))
 #define MAX_RX_SGE_CNT                 (RX_SGE_CNT - 2)
-/* RX_SGE_CNT is promissed to be a power of 2 */
+/* RX_SGE_CNT is promised to be a power of 2 */
 #define RX_SGE_MASK                    (RX_SGE_CNT - 1)
 #define NUM_RX_SGE                     (RX_SGE_CNT * NUM_RX_SGE_PAGES)
 #define MAX_RX_SGE                     (NUM_RX_SGE - 1)
@@ -258,8 +250,7 @@ struct bnx2x_fastpath {
 
        unsigned long           tx_pkt,
                                rx_pkt,
-                               rx_calls,
-                               rx_alloc_failed;
+                               rx_calls;
        /* TPA related */
        struct sw_rx_bd         tpa_pool[ETH_MAX_AGGREGATION_QUEUES_E1H];
        u8                      tpa_state[ETH_MAX_AGGREGATION_QUEUES_E1H];
@@ -275,6 +266,15 @@ struct bnx2x_fastpath {
 
 #define bnx2x_fp(bp, nr, var)          (bp->fp[nr].var)
 
+#define BNX2X_HAS_TX_WORK(fp) \
+                       ((fp->tx_pkt_prod != le16_to_cpu(*fp->tx_cons_sb)) || \
+                        (fp->tx_pkt_prod != fp->tx_pkt_cons))
+
+#define BNX2X_HAS_RX_WORK(fp) \
+                       (fp->rx_comp_cons != le16_to_cpu(*fp->rx_cons_sb))
+
+#define BNX2X_HAS_WORK(fp)     (BNX2X_HAS_RX_WORK(fp) || BNX2X_HAS_TX_WORK(fp))
+
 
 /* MC hsi */
 #define MAX_FETCH_BD                   13      /* HW max BDs per packet */
@@ -317,7 +317,7 @@ struct bnx2x_fastpath {
 #define RCQ_BD(x)                      ((x) & MAX_RCQ_BD)
 
 
-/* This is needed for determening of last_max */
+/* This is needed for determining of last_max */
 #define SUB_S16(a, b)                  (s16)((s16)(a) - (s16)(b))
 
 #define __SGE_MASK_SET_BIT(el, bit) \
@@ -386,20 +386,28 @@ struct bnx2x_fastpath {
 #define TPA_TYPE(cqe_fp_flags)         ((cqe_fp_flags) & \
                                         (TPA_TYPE_START | TPA_TYPE_END))
 
-#define BNX2X_RX_SUM_OK(cqe) \
-                       (!(cqe->fast_path_cqe.status_flags & \
-                        (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | \
-                         ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)))
+#define ETH_RX_ERROR_FALGS             ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG
+
+#define BNX2X_IP_CSUM_ERR(cqe) \
+                       (!((cqe)->fast_path_cqe.status_flags & \
+                          ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG) && \
+                        ((cqe)->fast_path_cqe.type_error_flags & \
+                         ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG))
+
+#define BNX2X_L4_CSUM_ERR(cqe) \
+                       (!((cqe)->fast_path_cqe.status_flags & \
+                          ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) && \
+                        ((cqe)->fast_path_cqe.type_error_flags & \
+                         ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG))
+
+#define BNX2X_RX_CSUM_OK(cqe) \
+                       (!(BNX2X_L4_CSUM_ERR(cqe) || BNX2X_IP_CSUM_ERR(cqe)))
 
 #define BNX2X_RX_SUM_FIX(cqe) \
                        ((le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & \
                          PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) == \
                         (1 << PARSING_FLAGS_OVER_ETHERNET_PROTOCOL_SHIFT))
 
-#define ETH_RX_ERROR_FALGS     (ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG | \
-                                ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | \
-                                ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG)
-
 
 #define FP_USB_FUNC_OFF                        (2 + 2*HC_USTORM_SB_NUM_INDICES)
 #define FP_CSB_FUNC_OFF                        (2 + 2*HC_CSTORM_SB_NUM_INDICES)
@@ -647,6 +655,8 @@ struct bnx2x_eth_stats {
 
        u32 brb_drop_hi;
        u32 brb_drop_lo;
+       u32 brb_truncate_hi;
+       u32 brb_truncate_lo;
 
        u32 jabber_packets_received;
 
@@ -663,6 +673,9 @@ struct bnx2x_eth_stats {
        u32 mac_discard;
 
        u32 driver_xoff;
+       u32 rx_err_discard_pkt;
+       u32 rx_skb_alloc_failed;
+       u32 hw_csum_err;
 };
 
 #define STATS_OFFSET32(stat_name) \
@@ -753,7 +766,6 @@ struct bnx2x {
        u16                     def_att_idx;
        u32                     attn_state;
        struct attn_route       attn_group[MAX_DYNAMIC_ATTN_GRPS];
-       u32                     aeu_mask;
        u32                     nig_mask;
 
        /* slow path ring */
@@ -772,7 +784,7 @@ struct bnx2x {
        u8                      stats_pending;
        u8                      set_mac_pending;
 
-       /* End of fileds used in the performance code paths */
+       /* End of fields used in the performance code paths */
 
        int                     panic;
        int                     msglevel;
@@ -794,9 +806,6 @@ struct bnx2x {
 #define BP_FUNC(bp)                    (bp->func)
 #define BP_E1HVN(bp)                   (bp->func >> 1)
 #define BP_L_ID(bp)                    (BP_E1HVN(bp) << 2)
-/* assorted E1HVN */
-#define IS_E1HMF(bp)                   (bp->e1hmf != 0)
-#define BP_MAX_QUEUES(bp)              (IS_E1HMF(bp) ? 4 : 16)
 
        int                     pm_cap;
        int                     pcie_cap;
@@ -821,6 +830,7 @@ struct bnx2x {
        u32                     mf_config;
        u16                     e1hov;
        u8                      e1hmf;
+#define IS_E1HMF(bp)                   (bp->e1hmf != 0)
 
        u8                      wol;
 
@@ -836,7 +846,6 @@ struct bnx2x {
        u16                     rx_ticks_int;
        u16                     rx_ticks;
 
-       u32                     stats_ticks;
        u32                     lin_cnt;
 
        int                     state;
@@ -852,6 +861,7 @@ struct bnx2x {
 #define BNX2X_STATE_ERROR              0xf000
 
        int                     num_queues;
+#define BP_MAX_QUEUES(bp)              (IS_E1HMF(bp) ? 4 : 16)
 
        u32                     rx_mode;
 #define BNX2X_RX_MODE_NONE             0
@@ -902,10 +912,17 @@ struct bnx2x {
 };
 
 
+#define for_each_queue(bp, var)        for (var = 0; var < bp->num_queues; var++)
+
+#define for_each_nondefault_queue(bp, var) \
+                               for (var = 1; var < bp->num_queues; var++)
+#define is_multi(bp)           (bp->num_queues > 1)
+
+
 void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32);
 void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
                      u32 len32);
-int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode);
+int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
 
 static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
                           int wait)
@@ -976,7 +993,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 #define PCICFG_LINK_SPEED_SHIFT                16
 
 
-#define BNX2X_NUM_STATS                        39
+#define BNX2X_NUM_STATS                        42
 #define BNX2X_NUM_TESTS                        8
 
 #define BNX2X_MAC_LOOPBACK             0
@@ -1007,10 +1024,10 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 /* resolution of the rate shaping timer - 100 usec */
 #define RS_PERIODIC_TIMEOUT_USEC       100
 /* resolution of fairness algorithm in usecs -
-   coefficient for clauclating the actuall t fair */
+   coefficient for calculating the actual t fair */
 #define T_FAIR_COEF                    10000000
 /* number of bytes in single QM arbitration cycle -
-   coeffiecnt for calculating the fairness timer */
+   coefficient for calculating the fairness timer */
 #define QM_ARB_BYTES                   40000
 #define FAIR_MEM                       2
 
index e3da7f69d27b8402916c7ba01f9e6ebd46625ea2..192fa981b9307b93f7509c370d3344fcdd4a67b2 100644 (file)
 
 
 #define CSTORM_ASSERT_LIST_INDEX_OFFSET \
-       (IS_E1H_OFFSET? 0x7000 : 0x1000)
+       (IS_E1H_OFFSET ? 0x7000 : 0x1000)
 #define CSTORM_ASSERT_LIST_OFFSET(idx) \
-       (IS_E1H_OFFSET? (0x7020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
+       (IS_E1H_OFFSET ? (0x7020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
 #define CSTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
-       (IS_E1H_OFFSET? (0x8522 + ((function>>1) * 0x40) + ((function&1) \
-       * 0x100) + (index * 0x4)) : (0x1922 + (function * 0x40) + (index \
-       * 0x4)))
+       (IS_E1H_OFFSET ? (0x8522 + ((function>>1) * 0x40) + \
+       ((function&1) * 0x100) + (index * 0x4)) : (0x1922 + (function * \
+       0x40) + (index * 0x4)))
 #define CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x8500 + ((function>>1) * 0x40) + ((function&1) \
-       * 0x100)) : (0x1900 + (function * 0x40)))
+       (IS_E1H_OFFSET ? (0x8500 + ((function>>1) * 0x40) + \
+       ((function&1) * 0x100)) : (0x1900 + (function * 0x40)))
 #define CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x8508 + ((function>>1) * 0x40) + ((function&1) \
-       * 0x100)) : (0x1908 + (function * 0x40)))
+       (IS_E1H_OFFSET ? (0x8508 + ((function>>1) * 0x40) + \
+       ((function&1) * 0x100)) : (0x1908 + (function * 0x40)))
 #define CSTORM_FUNCTION_MODE_OFFSET \
-       (IS_E1H_OFFSET? 0x11e8 : 0xffffffff)
+       (IS_E1H_OFFSET ? 0x11e8 : 0xffffffff)
 #define CSTORM_HC_BTR_OFFSET(port) \
-       (IS_E1H_OFFSET? (0x8704 + (port * 0xf0)) : (0x1984 + (port * 0xc0)))
+       (IS_E1H_OFFSET ? (0x8704 + (port * 0xf0)) : (0x1984 + (port * 0xc0)))
 #define CSTORM_SB_HC_DISABLE_OFFSET(port, cpu_id, index) \
-       (IS_E1H_OFFSET? (0x801a + (port * 0x280) + (cpu_id * 0x28) + \
+       (IS_E1H_OFFSET ? (0x801a + (port * 0x280) + (cpu_id * 0x28) + \
        (index * 0x4)) : (0x141a + (port * 0x280) + (cpu_id * 0x28) + \
        (index * 0x4)))
 #define CSTORM_SB_HC_TIMEOUT_OFFSET(port, cpu_id, index) \
-       (IS_E1H_OFFSET? (0x8018 + (port * 0x280) + (cpu_id * 0x28) + \
+       (IS_E1H_OFFSET ? (0x8018 + (port * 0x280) + (cpu_id * 0x28) + \
        (index * 0x4)) : (0x1418 + (port * 0x280) + (cpu_id * 0x28) + \
        (index * 0x4)))
 #define CSTORM_SB_HOST_SB_ADDR_OFFSET(port, cpu_id) \
-       (IS_E1H_OFFSET? (0x8000 + (port * 0x280) + (cpu_id * 0x28)) : \
+       (IS_E1H_OFFSET ? (0x8000 + (port * 0x280) + (cpu_id * 0x28)) : \
        (0x1400 + (port * 0x280) + (cpu_id * 0x28)))
 #define CSTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, cpu_id) \
-       (IS_E1H_OFFSET? (0x8008 + (port * 0x280) + (cpu_id * 0x28)) : \
+       (IS_E1H_OFFSET ? (0x8008 + (port * 0x280) + (cpu_id * 0x28)) : \
        (0x1408 + (port * 0x280) + (cpu_id * 0x28)))
 #define CSTORM_STATS_FLAGS_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x1108 + (function * 0x8)) : (0x5108 + \
+       (IS_E1H_OFFSET ? (0x1108 + (function * 0x8)) : (0x5108 + \
        (function * 0x8)))
 #define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x31c0 + (function * 0x20)) : 0xffffffff)
+       (IS_E1H_OFFSET ? (0x31c0 + (function * 0x20)) : 0xffffffff)
 #define TSTORM_ASSERT_LIST_INDEX_OFFSET \
-       (IS_E1H_OFFSET? 0xa000 : 0x1000)
+       (IS_E1H_OFFSET ? 0xa000 : 0x1000)
 #define TSTORM_ASSERT_LIST_OFFSET(idx) \
-       (IS_E1H_OFFSET? (0xa020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
+       (IS_E1H_OFFSET ? (0xa020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
 #define TSTORM_CLIENT_CONFIG_OFFSET(port, client_id) \
-       (IS_E1H_OFFSET? (0x3358 + (port * 0x3e8) + (client_id * 0x28)) : \
-       (0x9c8 + (port * 0x2f8) + (client_id * 0x28)))
+       (IS_E1H_OFFSET ? (0x3358 + (port * 0x3e8) + (client_id * 0x28)) \
+       (0x9c8 + (port * 0x2f8) + (client_id * 0x28)))
 #define TSTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
-       (IS_E1H_OFFSET? (0xb01a + ((function>>1) * 0x28) + ((function&1) \
-       * 0xa0) + (index * 0x4)) : (0x141a + (function * 0x28) + (index * \
-       0x4)))
+       (IS_E1H_OFFSET ? (0xb01a + ((function>>1) * 0x28) + \
+       ((function&1) * 0xa0) + (index * 0x4)) : (0x141a + (function * \
+       0x28) + (index * 0x4)))
 #define TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(function) \
-       (IS_E1H_OFFSET? (0xb000 + ((function>>1) * 0x28) + ((function&1) \
-       * 0xa0)) : (0x1400 + (function * 0x28)))
+       (IS_E1H_OFFSET ? (0xb000 + ((function>>1) * 0x28) + \
+       ((function&1) * 0xa0)) : (0x1400 + (function * 0x28)))
 #define TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \
-       (IS_E1H_OFFSET? (0xb008 + ((function>>1) * 0x28) + ((function&1) \
-       * 0xa0)) : (0x1408 + (function * 0x28)))
+       (IS_E1H_OFFSET ? (0xb008 + ((function>>1) * 0x28) + \
+       ((function&1) * 0xa0)) : (0x1408 + (function * 0x28)))
 #define TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x2b80 + (function * 0x8)) : (0x4b68 + \
+       (IS_E1H_OFFSET ? (0x2b80 + (function * 0x8)) : (0x4b68 + \
        (function * 0x8)))
 #define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x3000 + (function * 0x38)) : (0x1500 + \
+       (IS_E1H_OFFSET ? (0x3000 + (function * 0x38)) : (0x1500 + \
        (function * 0x38)))
 #define TSTORM_FUNCTION_MODE_OFFSET \
-       (IS_E1H_OFFSET? 0x1ad0 : 0xffffffff)
+       (IS_E1H_OFFSET ? 0x1ad0 : 0xffffffff)
 #define TSTORM_HC_BTR_OFFSET(port) \
-       (IS_E1H_OFFSET? (0xb144 + (port * 0x30)) : (0x1454 + (port * 0x18)))
+       (IS_E1H_OFFSET ? (0xb144 + (port * 0x30)) : (0x1454 + (port * 0x18)))
 #define TSTORM_INDIRECTION_TABLE_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x12c8 + (function * 0x80)) : (0x22c8 + \
+       (IS_E1H_OFFSET ? (0x12c8 + (function * 0x80)) : (0x22c8 + \
        (function * 0x80)))
 #define TSTORM_INDIRECTION_TABLE_SIZE 0x80
 #define TSTORM_MAC_FILTER_CONFIG_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x3008 + (function * 0x38)) : (0x1508 + \
+       (IS_E1H_OFFSET ? (0x3008 + (function * 0x38)) : (0x1508 + \
        (function * 0x38)))
+#define TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \
+       (IS_E1H_OFFSET ? (0x2010 + (port * 0x5b0) + (stats_counter_id * \
+       0x50)) : (0x4000 + (port * 0x3f0) + (stats_counter_id * 0x38)))
 #define TSTORM_RX_PRODS_OFFSET(port, client_id) \
-       (IS_E1H_OFFSET? (0x3350 + (port * 0x3e8) + (client_id * 0x28)) : \
-       (0x9c0 + (port * 0x2f8) + (client_id * 0x28)))
+       (IS_E1H_OFFSET ? (0x3350 + (port * 0x3e8) + (client_id * 0x28)) \
+       (0x9c0 + (port * 0x2f8) + (client_id * 0x28)))
 #define TSTORM_STATS_FLAGS_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x2c00 + (function * 0x8)) : (0x4b88 + \
+       (IS_E1H_OFFSET ? (0x2c00 + (function * 0x8)) : (0x4b88 + \
        (function * 0x8)))
-#define TSTORM_TPA_EXIST_OFFSET (IS_E1H_OFFSET? 0x3b30 : 0x1c20)
-#define USTORM_AGG_DATA_OFFSET (IS_E1H_OFFSET? 0xa040 : 0x2c10)
-#define USTORM_AGG_DATA_SIZE (IS_E1H_OFFSET? 0x2440 : 0x1200)
+#define TSTORM_TPA_EXIST_OFFSET (IS_E1H_OFFSET ? 0x3b30 : 0x1c20)
+#define USTORM_AGG_DATA_OFFSET (IS_E1H_OFFSET ? 0xa040 : 0x2c10)
+#define USTORM_AGG_DATA_SIZE (IS_E1H_OFFSET ? 0x2440 : 0x1200)
 #define USTORM_ASSERT_LIST_INDEX_OFFSET \
-       (IS_E1H_OFFSET? 0x8000 : 0x1000)
+       (IS_E1H_OFFSET ? 0x8000 : 0x1000)
 #define USTORM_ASSERT_LIST_OFFSET(idx) \
-       (IS_E1H_OFFSET? (0x8020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
+       (IS_E1H_OFFSET ? (0x8020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
 #define USTORM_CQE_PAGE_BASE_OFFSET(port, clientId) \
-       (IS_E1H_OFFSET? (0x3298 + (port * 0x258) + (clientId * 0x18)) : \
+       (IS_E1H_OFFSET ? (0x3298 + (port * 0x258) + (clientId * 0x18)) : \
        (0x5450 + (port * 0x1c8) + (clientId * 0x18)))
 #define USTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
-       (IS_E1H_OFFSET? (0x951a + ((function>>1) * 0x28) + ((function&1) \
-       * 0xa0) + (index * 0x4)) : (0x191a + (function * 0x28) + (index * \
-       0x4)))
+       (IS_E1H_OFFSET ? (0x951a + ((function>>1) * 0x28) + \
+       ((function&1) * 0xa0) + (index * 0x4)) : (0x191a + (function * \
+       0x28) + (index * 0x4)))
 #define USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x9500 + ((function>>1) * 0x28) + ((function&1) \
-       * 0xa0)) : (0x1900 + (function * 0x28)))
+       (IS_E1H_OFFSET ? (0x9500 + ((function>>1) * 0x28) + \
+       ((function&1) * 0xa0)) : (0x1900 + (function * 0x28)))
 #define USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x9508 + ((function>>1) * 0x28) + ((function&1) \
-       * 0xa0)) : (0x1908 + (function * 0x28)))
+       (IS_E1H_OFFSET ? (0x9508 + ((function>>1) * 0x28) + \
+       ((function&1) * 0xa0)) : (0x1908 + (function * 0x28)))
 #define USTORM_FUNCTION_MODE_OFFSET \
-       (IS_E1H_OFFSET? 0x2448 : 0xffffffff)
+       (IS_E1H_OFFSET ? 0x2448 : 0xffffffff)
 #define USTORM_HC_BTR_OFFSET(port) \
-       (IS_E1H_OFFSET? (0x9644 + (port * 0xd0)) : (0x1954 + (port * 0xb8)))
+       (IS_E1H_OFFSET ? (0x9644 + (port * 0xd0)) : (0x1954 + (port * 0xb8)))
 #define USTORM_MAX_AGG_SIZE_OFFSET(port, clientId) \
-       (IS_E1H_OFFSET? (0x3290 + (port * 0x258) + (clientId * 0x18)) : \
+       (IS_E1H_OFFSET ? (0x3290 + (port * 0x258) + (clientId * 0x18)) : \
        (0x5448 + (port * 0x1c8) + (clientId * 0x18)))
 #define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x2408 + (function * 0x8)) : (0x5408 + \
+       (IS_E1H_OFFSET ? (0x2408 + (function * 0x8)) : (0x5408 + \
        (function * 0x8)))
 #define USTORM_SB_HC_DISABLE_OFFSET(port, cpu_id, index) \
-       (IS_E1H_OFFSET? (0x901a + (port * 0x280) + (cpu_id * 0x28) + \
+       (IS_E1H_OFFSET ? (0x901a + (port * 0x280) + (cpu_id * 0x28) + \
        (index * 0x4)) : (0x141a + (port * 0x280) + (cpu_id * 0x28) + \
        (index * 0x4)))
 #define USTORM_SB_HC_TIMEOUT_OFFSET(port, cpu_id, index) \
-       (IS_E1H_OFFSET? (0x9018 + (port * 0x280) + (cpu_id * 0x28) + \
+       (IS_E1H_OFFSET ? (0x9018 + (port * 0x280) + (cpu_id * 0x28) + \
        (index * 0x4)) : (0x1418 + (port * 0x280) + (cpu_id * 0x28) + \
        (index * 0x4)))
 #define USTORM_SB_HOST_SB_ADDR_OFFSET(port, cpu_id) \
-       (IS_E1H_OFFSET? (0x9000 + (port * 0x280) + (cpu_id * 0x28)) : \
+       (IS_E1H_OFFSET ? (0x9000 + (port * 0x280) + (cpu_id * 0x28)) : \
        (0x1400 + (port * 0x280) + (cpu_id * 0x28)))
 #define USTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, cpu_id) \
-       (IS_E1H_OFFSET? (0x9008 + (port * 0x280) + (cpu_id * 0x28)) : \
+       (IS_E1H_OFFSET ? (0x9008 + (port * 0x280) + (cpu_id * 0x28)) : \
        (0x1408 + (port * 0x280) + (cpu_id * 0x28)))
 #define XSTORM_ASSERT_LIST_INDEX_OFFSET \
-       (IS_E1H_OFFSET? 0x9000 : 0x1000)
+       (IS_E1H_OFFSET ? 0x9000 : 0x1000)
 #define XSTORM_ASSERT_LIST_OFFSET(idx) \
-       (IS_E1H_OFFSET? (0x9020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
+       (IS_E1H_OFFSET ? (0x9020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
 #define XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) \
-       (IS_E1H_OFFSET? (0x24a8 + (port * 0x40)) : (0x3ba0 + (port * 0x40)))
+       (IS_E1H_OFFSET ? (0x24a8 + (port * 0x40)) : (0x3ba0 + (port * 0x40)))
 #define XSTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
-       (IS_E1H_OFFSET? (0xa01a + ((function>>1) * 0x28) + ((function&1) \
-       * 0xa0) + (index * 0x4)) : (0x141a + (function * 0x28) + (index * \
-       0x4)))
+       (IS_E1H_OFFSET ? (0xa01a + ((function>>1) * 0x28) + \
+       ((function&1) * 0xa0) + (index * 0x4)) : (0x141a + (function * \
+       0x28) + (index * 0x4)))
 #define XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(function) \
-       (IS_E1H_OFFSET? (0xa000 + ((function>>1) * 0x28) + ((function&1) \
-       * 0xa0)) : (0x1400 + (function * 0x28)))
+       (IS_E1H_OFFSET ? (0xa000 + ((function>>1) * 0x28) + \
+       ((function&1) * 0xa0)) : (0x1400 + (function * 0x28)))
 #define XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \
-       (IS_E1H_OFFSET? (0xa008 + ((function>>1) * 0x28) + ((function&1) \
-       * 0xa0)) : (0x1408 + (function * 0x28)))
+       (IS_E1H_OFFSET ? (0xa008 + ((function>>1) * 0x28) + \
+       ((function&1) * 0xa0)) : (0x1408 + (function * 0x28)))
 #define XSTORM_E1HOV_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x2ab8 + (function * 0x2)) : 0xffffffff)
+       (IS_E1H_OFFSET ? (0x2ab8 + (function * 0x2)) : 0xffffffff)
 #define XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x2418 + (function * 0x8)) : (0x3b70 + \
+       (IS_E1H_OFFSET ? (0x2418 + (function * 0x8)) : (0x3b70 + \
        (function * 0x8)))
 #define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x2568 + (function * 0x70)) : (0x3c60 + \
+       (IS_E1H_OFFSET ? (0x2568 + (function * 0x70)) : (0x3c60 + \
        (function * 0x70)))
 #define XSTORM_FUNCTION_MODE_OFFSET \
-       (IS_E1H_OFFSET? 0x2ac8 : 0xffffffff)
+       (IS_E1H_OFFSET ? 0x2ac8 : 0xffffffff)
 #define XSTORM_HC_BTR_OFFSET(port) \
-       (IS_E1H_OFFSET? (0xa144 + (port * 0x30)) : (0x1454 + (port * 0x18)))
+       (IS_E1H_OFFSET ? (0xa144 + (port * 0x30)) : (0x1454 + (port * 0x18)))
+#define XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \
+       (IS_E1H_OFFSET ? (0xc000 + (port * 0x3f0) + (stats_counter_id * \
+       0x38)) : (0x3378 + (port * 0x3f0) + (stats_counter_id * 0x38)))
 #define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x2528 + (function * 0x70)) : (0x3c20 + \
+       (IS_E1H_OFFSET ? (0x2528 + (function * 0x70)) : (0x3c20 + \
        (function * 0x70)))
 #define XSTORM_SPQ_PAGE_BASE_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x2000 + (function * 0x10)) : (0x3328 + \
+       (IS_E1H_OFFSET ? (0x2000 + (function * 0x10)) : (0x3328 + \
        (function * 0x10)))
 #define XSTORM_SPQ_PROD_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x2008 + (function * 0x10)) : (0x3330 + \
+       (IS_E1H_OFFSET ? (0x2008 + (function * 0x10)) : (0x3330 + \
        (function * 0x10)))
 #define XSTORM_STATS_FLAGS_OFFSET(function) \
-       (IS_E1H_OFFSET? (0x23d8 + (function * 0x8)) : (0x3b60 + \
+       (IS_E1H_OFFSET ? (0x23d8 + (function * 0x8)) : (0x3b60 + \
        (function * 0x8)))
 #define COMMON_ASM_INVALID_ASSERT_OPCODE 0x0
 
index d3e8198d7dba1dc6bfc1fd0696df3c178bc7ade9..efd764427fa12785284a924f2a8f7ca2e8dc98eb 100644 (file)
@@ -1268,7 +1268,7 @@ struct doorbell {
 
 
 /*
- * IGU driver acknowlegement register
+ * IGU driver acknowledgement register
  */
 struct igu_ack_register {
 #if defined(__BIG_ENDIAN)
@@ -1882,7 +1882,7 @@ struct timers_block_context {
 };
 
 /*
- * structure for easy accessability to assembler
+ * structure for easy accessibility to assembler
  */
 struct eth_tx_bd_flags {
        u8 as_bitfield;
@@ -2044,7 +2044,7 @@ struct eth_context {
 
 
 /*
- * ethernet doorbell
+ * Ethernet doorbell
  */
 struct eth_tx_doorbell {
 #if defined(__BIG_ENDIAN)
@@ -2256,7 +2256,7 @@ struct ramrod_data {
 };
 
 /*
- * union for ramrod data for ethernet protocol (CQE) (force size of 16 bits)
+ * union for ramrod data for Ethernet protocol (CQE) (force size of 16 bits)
  */
 union eth_ramrod_data {
        struct ramrod_data general;
@@ -2330,7 +2330,7 @@ struct spe_hdr {
 };
 
 /*
- * ethernet slow path element
+ * Ethernet slow path element
  */
 union eth_specific_data {
        u8 protocol_data[8];
@@ -2343,7 +2343,7 @@ union eth_specific_data {
 };
 
 /*
- * ethernet slow path element
+ * Ethernet slow path element
  */
 struct eth_spe {
        struct spe_hdr hdr;
@@ -2615,7 +2615,7 @@ struct tstorm_eth_rx_producers {
 
 
 /*
- * common flag to indicate existance of TPA.
+ * common flag to indicate existence of TPA.
  */
 struct tstorm_eth_tpa_exist {
 #if defined(__BIG_ENDIAN)
@@ -2765,7 +2765,7 @@ struct tstorm_common_stats {
 };
 
 /*
- * Eth statistics query sturcture for the eth_stats_quesry ramrod
+ * Eth statistics query structure for the eth_stats_query ramrod
  */
 struct eth_stats_query {
        struct xstorm_common_stats xstorm_common;
index 4c7750789b62309ca7d410c51122dbafa395d394..130927cfc75b63c79f986280029ddc4596f81c46 100644 (file)
 
 
 struct raw_op {
-       u32 op          :8;
-       u32 offset      :24;
+       u32 op:8;
+       u32 offset:24;
        u32 raw_data;
 };
 
 struct op_read {
-       u32 op          :8;
-       u32 offset      :24;
+       u32 op:8;
+       u32 offset:24;
        u32 pad;
 };
 
 struct op_write {
-       u32 op          :8;
-       u32 offset      :24;
+       u32 op:8;
+       u32 offset:24;
        u32 val;
 };
 
 struct op_string_write {
-       u32 op          :8;
-       u32 offset      :24;
+       u32 op:8;
+       u32 offset:24;
 #ifdef __LITTLE_ENDIAN
        u16 data_off;
        u16 data_len;
@@ -102,8 +102,8 @@ struct op_string_write {
 };
 
 struct op_zero {
-       u32 op          :8;
-       u32 offset      :24;
+       u32 op:8;
+       u32 offset:24;
        u32 len;
 };
 
@@ -208,7 +208,7 @@ static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
 /*********************************************************
    There are different blobs for each PRAM section.
    In addition, each blob write operation is divided into a few operations
-   in order to decrease the amount of phys. contigious buffer needed.
+   in order to decrease the amount of phys. contiguous buffer needed.
    Thus, when we select a blob the address may be with some offset
    from the beginning of PRAM section.
    The same holds for the INT_TABLE sections.
@@ -336,7 +336,7 @@ static void bnx2x_init_block(struct bnx2x *bp, u32 op_start, u32 op_end)
                len = op->str_wr.data_len;
                data = data_base + op->str_wr.data_off;
 
-               /* carefull! it must be in order */
+               /* careful! it must be in order */
                if (unlikely(op_type > OP_WB)) {
 
                        /* If E1 only */
@@ -740,7 +740,7 @@ static u8 calc_crc8(u32 data, u8 crc)
        return crc_res;
 }
 
-/* regiesers addresses are not in order
+/* registers addresses are not in order
    so these arrays help simplify the code */
 static const int cm_start[E1H_FUNC_MAX][9] = {
        {MISC_FUNC0_START, TCM_FUNC0_START, UCM_FUNC0_START, CCM_FUNC0_START,
index 63019055e4bb56962ba5767f662136a787921c4f..9755bf6b08ddff3b4abe47fd2d573e3676912dee 100644 (file)
@@ -901,31 +901,28 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3760, 0x4},
        {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1e20, 0x42},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3738, 0x9},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3000, 0x400},
+       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4b68, 0x2},
        {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x3738 + 0x24, 0x10293},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x2c00, 0x2},
+       {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x4b68 + 0x8, 0x20278},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3180, 0x42},
-       {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x2c00 + 0x8, 0x20278},
+       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4b10, 0x2},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5000, 0x400},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4b68, 0x2},
+       {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x2830, 0x2027a},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4000, 0x2},
-       {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x4b68 + 0x8, 0x2027a},
        {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x4000 + 0x8, 0x20294},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4b10, 0x2},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b68, 0x2},
-       {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x2830, 0x2027c},
        {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x6b68 + 0x8, 0x20296},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b10, 0x2},
        {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x74c0, 0x20298},
        {OP_WR, USEM_REG_FAST_MEMORY + 0x10800, 0x1000000},
-       {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x10c00, 0x10027e},
+       {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x10c00, 0x10027c},
        {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x10c00, 0x10029a},
        {OP_WR, USEM_REG_FAST_MEMORY + 0x10800, 0x0},
-       {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x10c40, 0x10028e},
+       {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x10c40, 0x10028c},
        {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x10c40, 0x1002aa},
        {OP_ZP_E1, USEM_REG_INT_TABLE, 0xc20000},
        {OP_ZP_E1H, USEM_REG_INT_TABLE, 0xc40000},
-       {OP_WR_64_E1, USEM_REG_INT_TABLE + 0x368, 0x13029e},
+       {OP_WR_64_E1, USEM_REG_INT_TABLE + 0x368, 0x13029c},
        {OP_WR_64_E1H, USEM_REG_INT_TABLE + 0x368, 0x1302ba},
        {OP_ZP_E1, USEM_REG_PRAM, 0x311c0000},
        {OP_ZP_E1H, USEM_REG_PRAM, 0x31070000},
@@ -933,11 +930,11 @@ static const struct raw_op init_ops[] = {
        {OP_ZP_E1H, USEM_REG_PRAM + 0x8000, 0x330e0c42},
        {OP_ZP_E1, USEM_REG_PRAM + 0x10000, 0x38561919},
        {OP_ZP_E1H, USEM_REG_PRAM + 0x10000, 0x389b1906},
-       {OP_WR_64_E1, USEM_REG_PRAM + 0x17fe0, 0x500402a0},
+       {OP_WR_64_E1, USEM_REG_PRAM + 0x17fe0, 0x5004029e},
        {OP_ZP_E1H, USEM_REG_PRAM + 0x18000, 0x132272d},
        {OP_WR_64_E1H, USEM_REG_PRAM + 0x18250, 0x4fb602bc},
-#define USEM_COMMON_END         790
-#define USEM_PORT0_START        790
+#define USEM_COMMON_END         787
+#define USEM_PORT0_START        787
        {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1400, 0xa0},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9000, 0xa0},
        {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1900, 0xa},
@@ -950,44 +947,27 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3288, 0x96},
        {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x5440, 0x72},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5000, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3000, 0x20},
+       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4b78, 0x52},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5100, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3100, 0x20},
+       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4e08, 0xc},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5200, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3200, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5300, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3300, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5400, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3400, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5500, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3500, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5600, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3600, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5700, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3700, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5800, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3800, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5900, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3900, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5a00, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3a00, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5b00, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3b00, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5c00, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3c00, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5d00, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3d00, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5e00, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3e00, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5f00, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3f00, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b78, 0x52},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x2c10, 0x2},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6e08, 0xc},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4b78, 0x52},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4e08, 0xc},
-#define USEM_PORT0_END          838
-#define USEM_PORT1_START        838
+#define USEM_PORT0_END          818
+#define USEM_PORT1_START        818
        {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1680, 0xa0},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9280, 0xa0},
        {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1928, 0xa},
@@ -1000,76 +980,59 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x34e0, 0x96},
        {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x5608, 0x72},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5080, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3080, 0x20},
+       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4cc0, 0x52},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5180, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3180, 0x20},
+       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4e38, 0xc},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5280, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3280, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5380, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3380, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5480, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3480, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5580, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3580, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5680, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3680, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5780, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3780, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5880, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3880, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5980, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3980, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5a80, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3a80, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5b80, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3b80, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5c80, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3c80, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5d80, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3d80, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5e80, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3e80, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5f80, 0x20},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x3f80, 0x20},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6cc0, 0x52},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x2c20, 0x2},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6e38, 0xc},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4cc0, 0x52},
-       {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4e38, 0xc},
-#define USEM_PORT1_END          886
-#define USEM_FUNC0_START        886
+#define USEM_PORT1_END          849
+#define USEM_FUNC0_START        849
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3000, 0x4},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4010, 0x2},
-#define USEM_FUNC0_END          888
-#define USEM_FUNC1_START        888
+#define USEM_FUNC0_END          851
+#define USEM_FUNC1_START        851
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3010, 0x4},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4020, 0x2},
-#define USEM_FUNC1_END          890
-#define USEM_FUNC2_START        890
+#define USEM_FUNC1_END          853
+#define USEM_FUNC2_START        853
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3020, 0x4},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4030, 0x2},
-#define USEM_FUNC2_END          892
-#define USEM_FUNC3_START        892
+#define USEM_FUNC2_END          855
+#define USEM_FUNC3_START        855
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3030, 0x4},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4040, 0x2},
-#define USEM_FUNC3_END          894
-#define USEM_FUNC4_START        894
+#define USEM_FUNC3_END          857
+#define USEM_FUNC4_START        857
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3040, 0x4},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4050, 0x2},
-#define USEM_FUNC4_END          896
-#define USEM_FUNC5_START        896
+#define USEM_FUNC4_END          859
+#define USEM_FUNC5_START        859
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3050, 0x4},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4060, 0x2},
-#define USEM_FUNC5_END          898
-#define USEM_FUNC6_START        898
+#define USEM_FUNC5_END          861
+#define USEM_FUNC6_START        861
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3060, 0x4},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4070, 0x2},
-#define USEM_FUNC6_END          900
-#define USEM_FUNC7_START        900
+#define USEM_FUNC6_END          863
+#define USEM_FUNC7_START        863
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3070, 0x4},
        {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4080, 0x2},
-#define USEM_FUNC7_END          902
-#define CSEM_COMMON_START       902
+#define USEM_FUNC7_END          865
+#define CSEM_COMMON_START       865
        {OP_RD, CSEM_REG_MSG_NUM_FIC0, 0x0},
        {OP_RD, CSEM_REG_MSG_NUM_FIC1, 0x0},
        {OP_RD, CSEM_REG_MSG_NUM_FOC0, 0x0},
@@ -1128,29 +1091,29 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x11e8, 0x0},
        {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x25c0, 0x240},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3000, 0xc0},
-       {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x2ec8, 0x802a2},
+       {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x2ec8, 0x802a0},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x4070, 0x80},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x5280, 0x4},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6280, 0x240},
        {OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x6b88, 0x2002be},
        {OP_WR, CSEM_REG_FAST_MEMORY + 0x10800, 0x13fffff},
-       {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x10c00, 0x1002aa},
+       {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x10c00, 0x1002a8},
        {OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x10c00, 0x1002de},
        {OP_WR, CSEM_REG_FAST_MEMORY + 0x10800, 0x0},
-       {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x10c40, 0x1002ba},
+       {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x10c40, 0x1002b8},
        {OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x10c40, 0x1002ee},
        {OP_ZP_E1, CSEM_REG_INT_TABLE, 0x6e0000},
        {OP_ZP_E1H, CSEM_REG_INT_TABLE, 0x6f0000},
-       {OP_WR_64_E1, CSEM_REG_INT_TABLE + 0x380, 0x1002ca},
+       {OP_WR_64_E1, CSEM_REG_INT_TABLE + 0x380, 0x1002c8},
        {OP_WR_64_E1H, CSEM_REG_INT_TABLE + 0x380, 0x1002fe},
        {OP_ZP_E1, CSEM_REG_PRAM, 0x32580000},
        {OP_ZP_E1H, CSEM_REG_PRAM, 0x31fa0000},
        {OP_ZP_E1, CSEM_REG_PRAM + 0x8000, 0x18270c96},
        {OP_ZP_E1H, CSEM_REG_PRAM + 0x8000, 0x19040c7f},
-       {OP_WR_64_E1, CSEM_REG_PRAM + 0xb210, 0x682402cc},
+       {OP_WR_64_E1, CSEM_REG_PRAM + 0xb210, 0x682402ca},
        {OP_WR_64_E1H, CSEM_REG_PRAM + 0xb430, 0x67e00300},
-#define CSEM_COMMON_END         981
-#define CSEM_PORT0_START        981
+#define CSEM_COMMON_END         944
+#define CSEM_PORT0_START        944
        {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1400, 0xa0},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8000, 0xa0},
        {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1900, 0x10},
@@ -1163,8 +1126,8 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6040, 0x30},
        {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x3040, 0x6},
        {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2410, 0x30},
-#define CSEM_PORT0_END          993
-#define CSEM_PORT1_START        993
+#define CSEM_PORT0_END          956
+#define CSEM_PORT1_START        956
        {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1680, 0xa0},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8280, 0xa0},
        {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1940, 0x10},
@@ -1177,43 +1140,43 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6100, 0x30},
        {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x3058, 0x6},
        {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x24d0, 0x30},
-#define CSEM_PORT1_END          1005
-#define CSEM_FUNC0_START        1005
+#define CSEM_PORT1_END          968
+#define CSEM_FUNC0_START        968
        {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1148, 0x0},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3300, 0x2},
-#define CSEM_FUNC0_END          1007
-#define CSEM_FUNC1_START        1007
+#define CSEM_FUNC0_END          970
+#define CSEM_FUNC1_START        970
        {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x114c, 0x0},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3308, 0x2},
-#define CSEM_FUNC1_END          1009
-#define CSEM_FUNC2_START        1009
+#define CSEM_FUNC1_END          972
+#define CSEM_FUNC2_START        972
        {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1150, 0x0},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3310, 0x2},
-#define CSEM_FUNC2_END          1011
-#define CSEM_FUNC3_START        1011
+#define CSEM_FUNC2_END          974
+#define CSEM_FUNC3_START        974
        {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1154, 0x0},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3318, 0x2},
-#define CSEM_FUNC3_END          1013
-#define CSEM_FUNC4_START        1013
+#define CSEM_FUNC3_END          976
+#define CSEM_FUNC4_START        976
        {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1158, 0x0},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3320, 0x2},
-#define CSEM_FUNC4_END          1015
-#define CSEM_FUNC5_START        1015
+#define CSEM_FUNC4_END          978
+#define CSEM_FUNC5_START        978
        {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x115c, 0x0},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3328, 0x2},
-#define CSEM_FUNC5_END          1017
-#define CSEM_FUNC6_START        1017
+#define CSEM_FUNC5_END          980
+#define CSEM_FUNC6_START        980
        {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1160, 0x0},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3330, 0x2},
-#define CSEM_FUNC6_END          1019
-#define CSEM_FUNC7_START        1019
+#define CSEM_FUNC6_END          982
+#define CSEM_FUNC7_START        982
        {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1164, 0x0},
        {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3338, 0x2},
-#define CSEM_FUNC7_END          1021
-#define XPB_COMMON_START        1021
+#define CSEM_FUNC7_END          984
+#define XPB_COMMON_START        984
        {OP_WR, GRCBASE_XPB + PB_REG_CONTROL, 0x20},
-#define XPB_COMMON_END          1022
-#define DQ_COMMON_START         1022
+#define XPB_COMMON_END          985
+#define DQ_COMMON_START         985
        {OP_WR, DORQ_REG_MODE_ACT, 0x2},
        {OP_WR, DORQ_REG_NORM_CID_OFST, 0x3},
        {OP_WR, DORQ_REG_OUTST_REQ, 0x4},
@@ -1232,8 +1195,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR, DORQ_REG_DQ_FIFO_AFULL_TH, 0x76c},
        {OP_WR, DORQ_REG_REGN, 0x7c1004},
        {OP_WR, DORQ_REG_IF_EN, 0xf},
-#define DQ_COMMON_END           1040
-#define TIMERS_COMMON_START     1040
+#define DQ_COMMON_END           1003
+#define TIMERS_COMMON_START     1003
        {OP_ZR, TM_REG_CLIN_PRIOR0_CLIENT, 0x2},
        {OP_WR, TM_REG_LIN_SETCLR_FIFO_ALFULL_THR, 0x1c},
        {OP_WR, TM_REG_CFC_AC_CRDCNT_VAL, 0x1},
@@ -1256,14 +1219,14 @@ static const struct raw_op init_ops[] = {
        {OP_WR, TM_REG_EN_CL0_INPUT, 0x1},
        {OP_WR, TM_REG_EN_CL1_INPUT, 0x1},
        {OP_WR, TM_REG_EN_CL2_INPUT, 0x1},
-#define TIMERS_COMMON_END       1062
-#define TIMERS_PORT0_START      1062
+#define TIMERS_COMMON_END       1025
+#define TIMERS_PORT0_START      1025
        {OP_ZR, TM_REG_LIN0_PHY_ADDR, 0x2},
-#define TIMERS_PORT0_END        1063
-#define TIMERS_PORT1_START      1063
+#define TIMERS_PORT0_END        1026
+#define TIMERS_PORT1_START      1026
        {OP_ZR, TM_REG_LIN1_PHY_ADDR, 0x2},
-#define TIMERS_PORT1_END        1064
-#define XSDM_COMMON_START       1064
+#define TIMERS_PORT1_END        1027
+#define XSDM_COMMON_START       1027
        {OP_WR_E1, XSDM_REG_CFC_RSP_START_ADDR, 0x614},
        {OP_WR_E1H, XSDM_REG_CFC_RSP_START_ADDR, 0x424},
        {OP_WR_E1, XSDM_REG_CMP_COUNTER_START_ADDR, 0x600},
@@ -1311,8 +1274,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_ASIC, XSDM_REG_TIMER_TICK, 0x3e8},
        {OP_WR_EMUL, XSDM_REG_TIMER_TICK, 0x1},
        {OP_WR_FPGA, XSDM_REG_TIMER_TICK, 0xa},
-#define XSDM_COMMON_END         1111
-#define QM_COMMON_START         1111
+#define XSDM_COMMON_END         1074
+#define QM_COMMON_START         1074
        {OP_WR, QM_REG_ACTCTRINITVAL_0, 0x6},
        {OP_WR, QM_REG_ACTCTRINITVAL_1, 0x5},
        {OP_WR, QM_REG_ACTCTRINITVAL_2, 0xa},
@@ -1613,8 +1576,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, QM_REG_PQ2PCIFUNC_6, 0x5},
        {OP_WR_E1H, QM_REG_PQ2PCIFUNC_7, 0x7},
        {OP_WR, QM_REG_CMINTEN, 0xff},
-#define QM_COMMON_END           1411
-#define PBF_COMMON_START        1411
+#define QM_COMMON_END           1374
+#define PBF_COMMON_START        1374
        {OP_WR, PBF_REG_INIT, 0x1},
        {OP_WR, PBF_REG_INIT_P4, 0x1},
        {OP_WR, PBF_REG_MAC_LB_ENABLE, 0x1},
@@ -1622,20 +1585,20 @@ static const struct raw_op init_ops[] = {
        {OP_WR, PBF_REG_INIT_P4, 0x0},
        {OP_WR, PBF_REG_INIT, 0x0},
        {OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P4, 0x0},
-#define PBF_COMMON_END          1418
-#define PBF_PORT0_START         1418
+#define PBF_COMMON_END          1381
+#define PBF_PORT0_START         1381
        {OP_WR, PBF_REG_INIT_P0, 0x1},
        {OP_WR, PBF_REG_MAC_IF0_ENABLE, 0x1},
        {OP_WR, PBF_REG_INIT_P0, 0x0},
        {OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P0, 0x0},
-#define PBF_PORT0_END           1422
-#define PBF_PORT1_START         1422
+#define PBF_PORT0_END           1385
+#define PBF_PORT1_START         1385
        {OP_WR, PBF_REG_INIT_P1, 0x1},
        {OP_WR, PBF_REG_MAC_IF1_ENABLE, 0x1},
        {OP_WR, PBF_REG_INIT_P1, 0x0},
        {OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P1, 0x0},
-#define PBF_PORT1_END           1426
-#define XCM_COMMON_START        1426
+#define PBF_PORT1_END           1389
+#define XCM_COMMON_START        1389
        {OP_WR, XCM_REG_XX_OVFL_EVNT_ID, 0x32},
        {OP_WR, XCM_REG_XQM_XCM_HDR_P, 0x3150020},
        {OP_WR, XCM_REG_XQM_XCM_HDR_S, 0x3150020},
@@ -1670,7 +1633,7 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1, XCM_REG_XX_MSG_NUM, 0x1f},
        {OP_WR_E1H, XCM_REG_XX_MSG_NUM, 0x20},
        {OP_ZR, XCM_REG_XX_TABLE, 0x12},
-       {OP_SW_E1, XCM_REG_XX_DESCR_TABLE, 0x1f02ce},
+       {OP_SW_E1, XCM_REG_XX_DESCR_TABLE, 0x1f02cc},
        {OP_SW_E1H, XCM_REG_XX_DESCR_TABLE, 0x1f0302},
        {OP_WR, XCM_REG_N_SM_CTX_LD_0, 0xf},
        {OP_WR, XCM_REG_N_SM_CTX_LD_1, 0x7},
@@ -1700,8 +1663,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR, XCM_REG_CDU_SM_WR_IFEN, 0x1},
        {OP_WR, XCM_REG_CDU_SM_RD_IFEN, 0x1},
        {OP_WR, XCM_REG_XCM_CFC_IFEN, 0x1},
-#define XCM_COMMON_END          1490
-#define XCM_PORT0_START         1490
+#define XCM_COMMON_END          1453
+#define XCM_PORT0_START         1453
        {OP_WR_E1, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8},
        {OP_WR_E1, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2},
        {OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0},
@@ -1710,8 +1673,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1, XCM_REG_WU_DA_CNT_CMD10, 0x2},
        {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff},
        {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff},
-#define XCM_PORT0_END           1498
-#define XCM_PORT1_START         1498
+#define XCM_PORT0_END           1461
+#define XCM_PORT1_START         1461
        {OP_WR_E1, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8},
        {OP_WR_E1, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2},
        {OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0},
@@ -1720,8 +1683,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1, XCM_REG_WU_DA_CNT_CMD11, 0x2},
        {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff},
        {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff},
-#define XCM_PORT1_END           1506
-#define XCM_FUNC0_START         1506
+#define XCM_PORT1_END           1469
+#define XCM_FUNC0_START         1469
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8},
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2},
        {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0},
@@ -1731,8 +1694,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff},
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff},
        {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0},
-#define XCM_FUNC0_END           1515
-#define XCM_FUNC1_START         1515
+#define XCM_FUNC0_END           1478
+#define XCM_FUNC1_START         1478
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8},
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2},
        {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0},
@@ -1742,8 +1705,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff},
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff},
        {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0},
-#define XCM_FUNC1_END           1524
-#define XCM_FUNC2_START         1524
+#define XCM_FUNC1_END           1487
+#define XCM_FUNC2_START         1487
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8},
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2},
        {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0},
@@ -1753,8 +1716,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff},
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff},
        {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0},
-#define XCM_FUNC2_END           1533
-#define XCM_FUNC3_START         1533
+#define XCM_FUNC2_END           1496
+#define XCM_FUNC3_START         1496
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8},
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2},
        {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0},
@@ -1764,8 +1727,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff},
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff},
        {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0},
-#define XCM_FUNC3_END           1542
-#define XCM_FUNC4_START         1542
+#define XCM_FUNC3_END           1505
+#define XCM_FUNC4_START         1505
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8},
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2},
        {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0},
@@ -1775,8 +1738,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff},
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff},
        {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0},
-#define XCM_FUNC4_END           1551
-#define XCM_FUNC5_START         1551
+#define XCM_FUNC4_END           1514
+#define XCM_FUNC5_START         1514
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8},
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2},
        {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0},
@@ -1786,8 +1749,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff},
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff},
        {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0},
-#define XCM_FUNC5_END           1560
-#define XCM_FUNC6_START         1560
+#define XCM_FUNC5_END           1523
+#define XCM_FUNC6_START         1523
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8},
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2},
        {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0},
@@ -1797,8 +1760,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff},
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff},
        {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0},
-#define XCM_FUNC6_END           1569
-#define XCM_FUNC7_START         1569
+#define XCM_FUNC6_END           1532
+#define XCM_FUNC7_START         1532
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8},
        {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2},
        {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0},
@@ -1808,8 +1771,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff},
        {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff},
        {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0},
-#define XCM_FUNC7_END           1578
-#define XSEM_COMMON_START       1578
+#define XCM_FUNC7_END           1541
+#define XSEM_COMMON_START       1541
        {OP_RD, XSEM_REG_MSG_NUM_FIC0, 0x0},
        {OP_RD, XSEM_REG_MSG_NUM_FIC1, 0x0},
        {OP_RD, XSEM_REG_MSG_NUM_FOC0, 0x0},
@@ -1876,9 +1839,9 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x9000, 0x2},
        {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3368, 0x0},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x21a8, 0x86},
-       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3370, 0x202ed},
+       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3370, 0x202eb},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2000, 0x20},
-       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3b90, 0x402ef},
+       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3b90, 0x402ed},
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x23c8, 0x0},
        {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1518, 0x1},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x23d0, 0x20321},
@@ -1886,29 +1849,29 @@ static const struct raw_op init_ops[] = {
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2498, 0x40323},
        {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1838, 0x0},
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x2ac8, 0x0},
-       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x1820, 0x202f3},
+       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x1820, 0x202f1},
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x2ab8, 0x0},
        {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4ac0, 0x2},
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x3010, 0x1},
        {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4b00, 0x4},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x4040, 0x10},
-       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x1f50, 0x202f5},
+       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x1f50, 0x202f3},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x4000, 0x100327},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6ac0, 0x2},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6b00, 0x4},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x83b0, 0x20337},
        {OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x0},
-       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c00, 0x1002f7},
+       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c00, 0x1002f5},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c00, 0x100339},
        {OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x1000000},
-       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c40, 0x80307},
+       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c40, 0x80305},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c40, 0x80349},
        {OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x2000000},
-       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c60, 0x8030f},
+       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c60, 0x8030d},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c60, 0x80351},
        {OP_ZP_E1, XSEM_REG_INT_TABLE, 0xa90000},
        {OP_ZP_E1H, XSEM_REG_INT_TABLE, 0xac0000},
-       {OP_WR_64_E1, XSEM_REG_INT_TABLE + 0x368, 0x130317},
+       {OP_WR_64_E1, XSEM_REG_INT_TABLE + 0x368, 0x130315},
        {OP_WR_64_E1H, XSEM_REG_INT_TABLE + 0x368, 0x130359},
        {OP_ZP_E1, XSEM_REG_PRAM, 0x344e0000},
        {OP_ZP_E1H, XSEM_REG_PRAM, 0x34620000},
@@ -1918,10 +1881,10 @@ static const struct raw_op init_ops[] = {
        {OP_ZP_E1H, XSEM_REG_PRAM + 0x10000, 0x3e971b22},
        {OP_ZP_E1, XSEM_REG_PRAM + 0x18000, 0x1dd02ad2},
        {OP_ZP_E1H, XSEM_REG_PRAM + 0x18000, 0x21542ac8},
-       {OP_WR_64_E1, XSEM_REG_PRAM + 0x1c0d0, 0x47e60319},
+       {OP_WR_64_E1, XSEM_REG_PRAM + 0x1c0d0, 0x47e60317},
        {OP_WR_64_E1H, XSEM_REG_PRAM + 0x1c8d0, 0x46e6035b},
-#define XSEM_COMMON_END         1688
-#define XSEM_PORT0_START        1688
+#define XSEM_COMMON_END         1651
+#define XSEM_PORT0_START        1651
        {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3ba0, 0x10},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xc000, 0xfc},
        {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3c20, 0x1c},
@@ -1934,7 +1897,7 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x26e8, 0x1c},
        {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3b58, 0x0},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x27c8, 0x1c},
-       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d10, 0x10031b},
+       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d10, 0x100319},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa000, 0x28},
        {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1500, 0x0},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa140, 0xc},
@@ -1950,12 +1913,12 @@ static const struct raw_op init_ops[] = {
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x6ac8, 0x2035d},
        {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x50b8, 0x1},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6b10, 0x42},
-       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x4ac8, 0x2032b},
+       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x4ac8, 0x20329},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6d20, 0x4},
        {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4b10, 0x42},
        {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4d20, 0x4},
-#define XSEM_PORT0_END          1720
-#define XSEM_PORT1_START        1720
+#define XSEM_PORT0_END          1683
+#define XSEM_PORT1_START        1683
        {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3be0, 0x10},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xc3f0, 0xfc},
        {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3c90, 0x1c},
@@ -1968,7 +1931,7 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2758, 0x1c},
        {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3b5c, 0x0},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2838, 0x1c},
-       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d50, 0x10032d},
+       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d50, 0x10032b},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa0a0, 0x28},
        {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1504, 0x0},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa170, 0xc},
@@ -1984,65 +1947,65 @@ static const struct raw_op init_ops[] = {
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x6ad0, 0x2035f},
        {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x50bc, 0x1},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6c18, 0x42},
-       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x4ad0, 0x2033d},
+       {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x4ad0, 0x2033b},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6d30, 0x4},
        {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4c18, 0x42},
        {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4d30, 0x4},
-#define XSEM_PORT1_END          1752
-#define XSEM_FUNC0_START        1752
+#define XSEM_PORT1_END          1715
+#define XSEM_FUNC0_START        1715
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e0, 0x0},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x28b8, 0x100361},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5048, 0xe},
-#define XSEM_FUNC0_END          1755
-#define XSEM_FUNC1_START        1755
+#define XSEM_FUNC0_END          1718
+#define XSEM_FUNC1_START        1718
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e4, 0x0},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x28f8, 0x100371},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5080, 0xe},
-#define XSEM_FUNC1_END          1758
-#define XSEM_FUNC2_START        1758
+#define XSEM_FUNC1_END          1721
+#define XSEM_FUNC2_START        1721
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e8, 0x0},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2938, 0x100381},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x50b8, 0xe},
-#define XSEM_FUNC2_END          1761
-#define XSEM_FUNC3_START        1761
+#define XSEM_FUNC2_END          1724
+#define XSEM_FUNC3_START        1724
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7ec, 0x0},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2978, 0x100391},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x50f0, 0xe},
-#define XSEM_FUNC3_END          1764
-#define XSEM_FUNC4_START        1764
+#define XSEM_FUNC3_END          1727
+#define XSEM_FUNC4_START        1727
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f0, 0x0},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29b8, 0x1003a1},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5128, 0xe},
-#define XSEM_FUNC4_END          1767
-#define XSEM_FUNC5_START        1767
+#define XSEM_FUNC4_END          1730
+#define XSEM_FUNC5_START        1730
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f4, 0x0},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29f8, 0x1003b1},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5160, 0xe},
-#define XSEM_FUNC5_END          1770
-#define XSEM_FUNC6_START        1770
+#define XSEM_FUNC5_END          1733
+#define XSEM_FUNC6_START        1733
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f8, 0x0},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2a38, 0x1003c1},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5198, 0xe},
-#define XSEM_FUNC6_END          1773
-#define XSEM_FUNC7_START        1773
+#define XSEM_FUNC6_END          1736
+#define XSEM_FUNC7_START        1736
        {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7fc, 0x0},
        {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2a78, 0x1003d1},
        {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x51d0, 0xe},
-#define XSEM_FUNC7_END          1776
-#define CDU_COMMON_START        1776
+#define XSEM_FUNC7_END          1739
+#define CDU_COMMON_START        1739
        {OP_WR, CDU_REG_CDU_CONTROL0, 0x1},
        {OP_WR_E1H, CDU_REG_MF_MODE, 0x1},
        {OP_WR, CDU_REG_CDU_CHK_MASK0, 0x3d000},
        {OP_WR, CDU_REG_CDU_CHK_MASK1, 0x3d},
-       {OP_WB_E1, CDU_REG_L1TT, 0x200033f},
+       {OP_WB_E1, CDU_REG_L1TT, 0x200033d},
        {OP_WB_E1H, CDU_REG_L1TT, 0x20003e1},
-       {OP_WB_E1, CDU_REG_MATT, 0x20053f},
+       {OP_WB_E1, CDU_REG_MATT, 0x20053d},
        {OP_WB_E1H, CDU_REG_MATT, 0x2805e1},
        {OP_ZR_E1, CDU_REG_MATT + 0x80, 0x2},
-       {OP_WB_E1, CDU_REG_MATT + 0x88, 0x6055f},
+       {OP_WB_E1, CDU_REG_MATT + 0x88, 0x6055d},
        {OP_ZR, CDU_REG_MATT + 0xa0, 0x18},
-#define CDU_COMMON_END          1787
-#define DMAE_COMMON_START       1787
+#define CDU_COMMON_END          1750
+#define DMAE_COMMON_START       1750
        {OP_ZR, DMAE_REG_CMD_MEM, 0xe0},
        {OP_WR, DMAE_REG_CRC16C_INIT, 0x0},
        {OP_WR, DMAE_REG_CRC16T10_INIT, 0x1},
@@ -2050,24 +2013,24 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, DMAE_REG_PXP_REQ_INIT_CRD, 0x2},
        {OP_WR, DMAE_REG_PCI_IFEN, 0x1},
        {OP_WR, DMAE_REG_GRC_IFEN, 0x1},
-#define DMAE_COMMON_END         1794
-#define PXP_COMMON_START        1794
-       {OP_WB_E1, PXP_REG_HST_INBOUND_INT + 0x400, 0x50565},
+#define DMAE_COMMON_END         1757
+#define PXP_COMMON_START        1757
+       {OP_WB_E1, PXP_REG_HST_INBOUND_INT + 0x400, 0x50563},
        {OP_WB_E1H, PXP_REG_HST_INBOUND_INT + 0x400, 0x50609},
-       {OP_WB_E1, PXP_REG_HST_INBOUND_INT + 0x420, 0x5056a},
+       {OP_WB_E1, PXP_REG_HST_INBOUND_INT + 0x420, 0x50568},
        {OP_WB_E1H, PXP_REG_HST_INBOUND_INT, 0x5060e},
-       {OP_WB_E1, PXP_REG_HST_INBOUND_INT, 0x5056f},
-#define PXP_COMMON_END          1799
-#define CFC_COMMON_START        1799
+       {OP_WB_E1, PXP_REG_HST_INBOUND_INT, 0x5056d},
+#define PXP_COMMON_END          1762
+#define CFC_COMMON_START        1762
        {OP_ZR_E1H, CFC_REG_LINK_LIST, 0x100},
        {OP_WR, CFC_REG_CONTROL0, 0x10},
        {OP_WR, CFC_REG_DISABLE_ON_ERROR, 0x3fff},
        {OP_WR, CFC_REG_LCREQ_WEIGHTS, 0x84924a},
-#define CFC_COMMON_END          1803
-#define HC_COMMON_START         1803
+#define CFC_COMMON_END          1766
+#define HC_COMMON_START         1766
        {OP_ZR_E1, HC_REG_USTORM_ADDR_FOR_COALESCE, 0x4},
-#define HC_COMMON_END           1804
-#define HC_PORT0_START          1804
+#define HC_COMMON_END           1767
+#define HC_PORT0_START          1767
        {OP_WR_E1, HC_REG_CONFIG_0, 0x1080},
        {OP_ZR_E1, HC_REG_UC_RAM_ADDR_0, 0x2},
        {OP_WR_E1, HC_REG_ATTN_NUM_P0, 0x10},
@@ -2086,8 +2049,8 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a},
        {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a},
        {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a},
-#define HC_PORT0_END            1822
-#define HC_PORT1_START          1822
+#define HC_PORT0_END            1785
+#define HC_PORT1_START          1785
        {OP_WR_E1, HC_REG_CONFIG_1, 0x1080},
        {OP_ZR_E1, HC_REG_UC_RAM_ADDR_1, 0x2},
        {OP_WR_E1, HC_REG_ATTN_NUM_P1, 0x10},
@@ -2106,8 +2069,8 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a},
        {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a},
        {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a},
-#define HC_PORT1_END            1840
-#define HC_FUNC0_START          1840
+#define HC_PORT1_END            1803
+#define HC_FUNC0_START          1803
        {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080},
        {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x0},
        {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10},
@@ -2123,8 +2086,8 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a},
-#define HC_FUNC0_END            1855
-#define HC_FUNC1_START          1855
+#define HC_FUNC0_END            1818
+#define HC_FUNC1_START          1818
        {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080},
        {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x1},
        {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10},
@@ -2140,8 +2103,8 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a},
-#define HC_FUNC1_END            1870
-#define HC_FUNC2_START          1870
+#define HC_FUNC1_END            1833
+#define HC_FUNC2_START          1833
        {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080},
        {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x2},
        {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10},
@@ -2157,8 +2120,8 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a},
-#define HC_FUNC2_END            1885
-#define HC_FUNC3_START          1885
+#define HC_FUNC2_END            1848
+#define HC_FUNC3_START          1848
        {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080},
        {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x3},
        {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10},
@@ -2174,8 +2137,8 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a},
-#define HC_FUNC3_END            1900
-#define HC_FUNC4_START          1900
+#define HC_FUNC3_END            1863
+#define HC_FUNC4_START          1863
        {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080},
        {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x4},
        {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10},
@@ -2191,8 +2154,8 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a},
-#define HC_FUNC4_END            1915
-#define HC_FUNC5_START          1915
+#define HC_FUNC4_END            1878
+#define HC_FUNC5_START          1878
        {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080},
        {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x5},
        {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10},
@@ -2208,8 +2171,8 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a},
-#define HC_FUNC5_END            1930
-#define HC_FUNC6_START          1930
+#define HC_FUNC5_END            1893
+#define HC_FUNC6_START          1893
        {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080},
        {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x6},
        {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10},
@@ -2225,8 +2188,8 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a},
-#define HC_FUNC6_END            1945
-#define HC_FUNC7_START          1945
+#define HC_FUNC6_END            1908
+#define HC_FUNC7_START          1908
        {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080},
        {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x7},
        {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10},
@@ -2242,8 +2205,8 @@ static const struct raw_op init_ops[] = {
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a},
        {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a},
-#define HC_FUNC7_END            1960
-#define PXP2_COMMON_START       1960
+#define HC_FUNC7_END            1923
+#define PXP2_COMMON_START       1923
        {OP_WR_E1, PXP2_REG_PGL_CONTROL0, 0xe38340},
        {OP_WR_E1H, PXP2_REG_RQ_DRAM_ALIGN, 0x1},
        {OP_WR, PXP2_REG_PGL_CONTROL1, 0x3c10},
@@ -2361,8 +2324,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, PXP2_REG_RQ_ILT_MODE, 0x1},
        {OP_WR, PXP2_REG_RQ_RBC_DONE, 0x1},
        {OP_WR_E1H, PXP2_REG_PGL_CONTROL0, 0xe38340},
-#define PXP2_COMMON_END         2077
-#define MISC_AEU_COMMON_START   2077
+#define PXP2_COMMON_END         2040
+#define MISC_AEU_COMMON_START   2040
        {OP_ZR, MISC_REG_AEU_GENERAL_ATTN_0, 0x16},
        {OP_WR_E1H, MISC_REG_AEU_ENABLE1_NIG_0, 0x55540000},
        {OP_WR_E1H, MISC_REG_AEU_ENABLE2_NIG_0, 0x55555555},
@@ -2382,8 +2345,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1H, MISC_REG_AEU_ENABLE4_PXP_1, 0x0},
        {OP_WR_E1H, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0xc00},
        {OP_WR_E1H, MISC_REG_AEU_GENERAL_MASK, 0x3},
-#define MISC_AEU_COMMON_END     2096
-#define MISC_AEU_PORT0_START    2096
+#define MISC_AEU_COMMON_END     2059
+#define MISC_AEU_PORT0_START    2059
        {OP_WR_E1, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, 0xbf5c0000},
        {OP_WR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, 0xff5c0000},
        {OP_WR_E1, MISC_REG_AEU_ENABLE2_FUNC_0_OUT_0, 0xfff51fef},
@@ -2416,8 +2379,8 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1, MISC_REG_AEU_INVERTER_1_FUNC_0, 0x0},
        {OP_ZR_E1, MISC_REG_AEU_INVERTER_2_FUNC_0, 0x3},
        {OP_WR_E1, MISC_REG_AEU_MASK_ATTN_FUNC_0, 0x7},
-#define MISC_AEU_PORT0_END      2128
-#define MISC_AEU_PORT1_START    2128
+#define MISC_AEU_PORT0_END      2091
+#define MISC_AEU_PORT1_START    2091
        {OP_WR_E1, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0, 0xbf5c0000},
        {OP_WR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0, 0xff5c0000},
        {OP_WR_E1, MISC_REG_AEU_ENABLE2_FUNC_1_OUT_0, 0xfff51fef},
@@ -2450,7 +2413,7 @@ static const struct raw_op init_ops[] = {
        {OP_WR_E1, MISC_REG_AEU_INVERTER_1_FUNC_1, 0x0},
        {OP_ZR_E1, MISC_REG_AEU_INVERTER_2_FUNC_1, 0x3},
        {OP_WR_E1, MISC_REG_AEU_MASK_ATTN_FUNC_1, 0x7},
-#define MISC_AEU_PORT1_END      2160
+#define MISC_AEU_PORT1_END      2123
 
 };
 
@@ -2560,103 +2523,92 @@ static const u32 init_data_e1[] = {
        0x00049c00, 0x00051f80, 0x0005a300, 0x00062680, 0x0006aa00, 0x00072d80,
        0x0007b100, 0x00083480, 0x0008b800, 0x00093b80, 0x0009bf00, 0x000a4280,
        0x000ac600, 0x000b4980, 0x000bcd00, 0x000c5080, 0x000cd400, 0x000d5780,
-       0x000ddb00, 0x00001900, 0x00000028, 0x00000000, 0x00100000, 0x00000000,
-       0x00000000, 0xffffffff, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
+       0x000ddb00, 0x00001900, 0x00100000, 0x00000000, 0x00000000, 0xffffffff,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
-       0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x00000000, 0x00007ff8,
-       0x00000000, 0x00001500, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
-       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
+       0x40000000, 0x40000000, 0x00000000, 0x00007ff8, 0x00000000, 0x00001500,
+       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+       0xffffffff, 0xffffffff, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
-       0x00000000, 0x00007ff8, 0x00000000, 0x00003500, 0x00001000, 0x00002080,
-       0x00003100, 0x00004180, 0x00005200, 0x00006280, 0x00007300, 0x00008380,
-       0x00009400, 0x0000a480, 0x0000b500, 0x0000c580, 0x0000d600, 0x0000e680,
-       0x0000f700, 0x00010780, 0x00011800, 0x00012880, 0x00013900, 0x00014980,
-       0x00015a00, 0x00016a80, 0x00017b00, 0x00018b80, 0x00019c00, 0x0001ac80,
-       0x0001bd00, 0x0001cd80, 0x0001de00, 0x0001ee80, 0x0001ff00, 0x00000000,
-       0x00010001, 0x00000604, 0xccccccc1, 0xffffffff, 0xffffffff, 0xcccc0201,
-       0xcccccccc, 0x00000000, 0xffffffff, 0x40000000, 0x40000000, 0x40000000,
+       0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x00000000, 0x00007ff8,
+       0x00000000, 0x00003500, 0x00001000, 0x00002080, 0x00003100, 0x00004180,
+       0x00005200, 0x00006280, 0x00007300, 0x00008380, 0x00009400, 0x0000a480,
+       0x0000b500, 0x0000c580, 0x0000d600, 0x0000e680, 0x0000f700, 0x00010780,
+       0x00011800, 0x00012880, 0x00013900, 0x00014980, 0x00015a00, 0x00016a80,
+       0x00017b00, 0x00018b80, 0x00019c00, 0x0001ac80, 0x0001bd00, 0x0001cd80,
+       0x0001de00, 0x0001ee80, 0x0001ff00, 0x00000000, 0x00010001, 0x00000604,
+       0xccccccc1, 0xffffffff, 0xffffffff, 0xcccc0201, 0xcccccccc, 0x00000000,
+       0xffffffff, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
        0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
-       0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x00000000,
-       0x00007ff8, 0x00000000, 0x00003500, 0x0000ffff, 0x00000000, 0x0000ffff,
+       0x40000000, 0x40000000, 0x40000000, 0x00000000, 0x00007ff8, 0x00000000,
+       0x00003500, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff,
        0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff,
+       0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x00100000,
        0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff,
-       0x00000000, 0x00100000, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff,
        0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff,
-       0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff,
-       0x00000000, 0x00100000, 0x00000000, 0xfffffff3, 0x320fffff, 0x0c30c30c,
-       0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1,
-       0x30efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c,
-       0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
-       0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305,
-       0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2,
-       0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c,
-       0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
-       0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xfffffff7, 0x31efffff, 0x0c30c30c,
-       0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5,
-       0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c,
-       0xcdcdcdcd, 0xfffffff3, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
-       0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x310fffff, 0x0c30c30c,
+       0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x00100000,
+       0x00000000, 0xfffffff3, 0x320fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
+       0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x30efffff, 0x0c30c30c,
        0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6,
        0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c,
        0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014,
        0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c,
        0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa,
        0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c,
-       0xcdcdcdcd, 0xfffffff7, 0x30efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
-       0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x304fffff, 0x0c30c30c,
+       0xcdcdcdcd, 0xfffffff7, 0x31efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
+       0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x302fffff, 0x0c30c30c,
        0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3,
-       0x31efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c,
+       0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c,
        0xcdcdcdcd, 0xfffffff1, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
        0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c,
        0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406,
        0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c,
        0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
        0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c,
-       0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffff97,
-       0x056fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0020cf3c,
-       0xcdcdcdcd, 0xfffffff5, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
-       0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, 0x320fffff, 0x0c30c30c,
+       0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xfffffff7,
+       0x30efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0020cf3c,
+       0xcdcdcdcd, 0xfffffff5, 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
+       0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, 0x31efffff, 0x0c30c30c,
        0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1,
        0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c,
        0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
        0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305,
        0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2,
        0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c,
-       0xcdcdcdcd, 0xffffff8a, 0x042fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000,
-       0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffff97, 0x05cfffff, 0x0c30c30c,
+       0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
+       0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffff97, 0x056fffff, 0x0c30c30c,
        0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5,
        0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c,
-       0xcdcdcdcd, 0xfffffff3, 0x300fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
-       0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x300fffff, 0x0c30c30c,
+       0xcdcdcdcd, 0xfffffff3, 0x320fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
+       0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x310fffff, 0x0c30c30c,
        0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6,
        0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c,
        0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014,
        0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c,
-       0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa,
-       0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c,
-       0xcdcdcdcd, 0xffffff97, 0x040fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000,
-       0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x300fffff, 0x0c30c30c,
-       0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xffffffff,
-       0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0000cf3c,
-       0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc,
-       0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c,
-       0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xffffffff,
-       0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0004cf3c,
-       0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc,
-       0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c,
-       0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffffff,
-       0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0020cf3c,
-       0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc,
+       0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xffffff8a,
+       0x042fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0010cf3c,
+       0xcdcdcdcd, 0xffffff97, 0x05cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000,
+       0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x310fffff, 0x0c30c30c,
+       0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3,
+       0x300fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c,
+       0xcdcdcdcd, 0xfffffff1, 0x300fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
+       0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c,
+       0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406,
+       0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c,
+       0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
+       0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c,
+       0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffff97,
+       0x040fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0020cf3c,
+       0xcdcdcdcd, 0xfffffff5, 0x300fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300,
        0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c,
        0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xffffffff,
        0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0001cf3c,
@@ -2678,16 +2630,27 @@ static const u32 init_data_e1[] = {
        0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0010cf3c,
        0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc,
        0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c,
-       0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0x00100000,
-       0x00070100, 0x00028170, 0x000b8198, 0x00020250, 0x00010270, 0x000f0280,
-       0x00010370, 0x00080000, 0x00080080, 0x00028100, 0x000b8128, 0x000201e0,
-       0x00010200, 0x00070210, 0x00020280, 0x000f0000, 0x000800f0, 0x00028170,
-       0x000b8198, 0x00020250, 0x00010270, 0x000b8280, 0x00080338, 0x00100000,
-       0x00080100, 0x00028180, 0x000b81a8, 0x00020260, 0x00018280, 0x000e8298,
-       0x00080380, 0x00028000, 0x000b8028, 0x000200e0, 0x00010100, 0x00008110,
-       0x00000118, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0x00002000,
-       0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0x00002000, 0xcccccccc,
-       0xcccccccc, 0xcccccccc, 0xcccccccc, 0x00002000
+       0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xffffffff,
+       0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0000cf3c,
+       0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc,
+       0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c,
+       0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xffffffff,
+       0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0004cf3c,
+       0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc,
+       0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c,
+       0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffffff,
+       0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0020cf3c,
+       0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc,
+       0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0x00100000, 0x00070100, 0x00028170,
+       0x000b8198, 0x00020250, 0x00010270, 0x000f0280, 0x00010370, 0x00080000,
+       0x00080080, 0x00028100, 0x000b8128, 0x000201e0, 0x00010200, 0x00070210,
+       0x00020280, 0x000f0000, 0x000800f0, 0x00028170, 0x000b8198, 0x00020250,
+       0x00010270, 0x000b8280, 0x00080338, 0x00100000, 0x00080100, 0x00028180,
+       0x000b81a8, 0x00020260, 0x00018280, 0x000e8298, 0x00080380, 0x00028000,
+       0x000b8028, 0x000200e0, 0x00010100, 0x00008110, 0x00000118, 0xcccccccc,
+       0xcccccccc, 0xcccccccc, 0xcccccccc, 0x00002000, 0xcccccccc, 0xcccccccc,
+       0xcccccccc, 0xcccccccc, 0x00002000, 0xcccccccc, 0xcccccccc, 0xcccccccc,
+       0xcccccccc, 0x00002000
 };
 
 static const u32 init_data_e1h[] = {
index ff2743db10d9ef69081a0d96762fcefe96d2de51..8b92c6ad0759107131e4d65211dad419c0b5e60f 100644 (file)
 
 /********************************************************/
 #define SUPPORT_CL73 0 /* Currently no */
-#define ETH_HLEN                       14
+#define ETH_HLEN                       14
 #define ETH_OVREHEAD           (ETH_HLEN + 8)/* 8 for CRC + VLAN*/
 #define ETH_MIN_PACKET_SIZE            60
 #define ETH_MAX_PACKET_SIZE            1500
 #define ETH_MAX_JUMBO_PACKET_SIZE      9600
 #define MDIO_ACCESS_TIMEOUT            1000
 #define BMAC_CONTROL_RX_ENABLE 2
-#define MAX_MTU_SIZE           5000
 
 /***********************************************************/
-/*                       Shortcut definitions              */
+/*                     Shortcut definitions               */
 /***********************************************************/
 
 #define NIG_STATUS_XGXS0_LINK10G \
 
 #define AUTONEG_CL37           SHARED_HW_CFG_AN_ENABLE_CL37
 #define AUTONEG_CL73           SHARED_HW_CFG_AN_ENABLE_CL73
-#define AUTONEG_BAM                    SHARED_HW_CFG_AN_ENABLE_BAM
-#define AUTONEG_PARALLEL               \
+#define AUTONEG_BAM            SHARED_HW_CFG_AN_ENABLE_BAM
+#define AUTONEG_PARALLEL \
                                SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
-#define AUTONEG_SGMII_FIBER_AUTODET    \
+#define AUTONEG_SGMII_FIBER_AUTODET \
                                SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
-#define AUTONEG_REMOTE_PHY             SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
+#define AUTONEG_REMOTE_PHY     SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
 
 #define GP_STATUS_PAUSE_RSOLUTION_TXSIDE \
                        MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE
@@ -202,11 +201,10 @@ static void bnx2x_emac_init(struct link_params *params,
        /* init emac - use read-modify-write */
        /* self clear reset */
        val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
-       EMAC_WR(EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
+       EMAC_WR(bp, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
 
        timeout = 200;
-       do
-       {
+       do {
                val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
                DP(NETIF_MSG_LINK, "EMAC reset reg is %u\n", val);
                if (!timeout) {
@@ -214,18 +212,18 @@ static void bnx2x_emac_init(struct link_params *params,
                        return;
                }
                timeout--;
-       }while (val & EMAC_MODE_RESET);
+       } while (val & EMAC_MODE_RESET);
 
        /* Set mac address */
        val = ((params->mac_addr[0] << 8) |
                params->mac_addr[1]);
-       EMAC_WR(EMAC_REG_EMAC_MAC_MATCH, val);
+       EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH, val);
 
        val = ((params->mac_addr[2] << 24) |
               (params->mac_addr[3] << 16) |
               (params->mac_addr[4] << 8) |
                params->mac_addr[5]);
-       EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + 4, val);
+       EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + 4, val);
 }
 
 static u8 bnx2x_emac_enable(struct link_params *params,
@@ -286,7 +284,7 @@ static u8 bnx2x_emac_enable(struct link_params *params,
        if (CHIP_REV_IS_SLOW(bp)) {
                /* config GMII mode */
                val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
-               EMAC_WR(EMAC_REG_EMAC_MODE,
+               EMAC_WR(bp, EMAC_REG_EMAC_MODE,
                            (val | EMAC_MODE_PORT_GMII));
        } else { /* ASIC */
                /* pause enable/disable */
@@ -298,17 +296,19 @@ static u8 bnx2x_emac_enable(struct link_params *params,
                                    EMAC_RX_MODE_FLOW_EN);
 
                bnx2x_bits_dis(bp,  emac_base + EMAC_REG_EMAC_TX_MODE,
-                              EMAC_TX_MODE_EXT_PAUSE_EN);
+                            (EMAC_TX_MODE_EXT_PAUSE_EN |
+                             EMAC_TX_MODE_FLOW_EN));
                if (vars->flow_ctrl & FLOW_CTRL_TX)
                        bnx2x_bits_en(bp, emac_base +
                                    EMAC_REG_EMAC_TX_MODE,
-                                     EMAC_TX_MODE_EXT_PAUSE_EN);
+                                  (EMAC_TX_MODE_EXT_PAUSE_EN |
+                                   EMAC_TX_MODE_FLOW_EN));
        }
 
        /* KEEP_VLAN_TAG, promiscuous */
        val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
        val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
-       EMAC_WR(EMAC_REG_EMAC_RX_MODE, val);
+       EMAC_WR(bp, EMAC_REG_EMAC_RX_MODE, val);
 
        /* Set Loopback */
        val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
@@ -316,10 +316,10 @@ static u8 bnx2x_emac_enable(struct link_params *params,
                val |= 0x810;
        else
                val &= ~0x810;
-       EMAC_WR(EMAC_REG_EMAC_MODE, val);
+       EMAC_WR(bp, EMAC_REG_EMAC_MODE, val);
 
        /* enable emac for jumbo packets */
-       EMAC_WR(EMAC_REG_EMAC_RX_MTU_SIZE,
+       EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE,
                (EMAC_RX_MTU_SIZE_JUMBO_ENA |
                 (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
 
@@ -591,9 +591,9 @@ void bnx2x_link_status_update(struct link_params *params,
                        vars->flow_ctrl &= ~FLOW_CTRL_RX;
 
                if (vars->phy_flags & PHY_XGXS_FLAG) {
-                       if (params->req_line_speed &&
-                           ((params->req_line_speed == SPEED_10) ||
-                            (params->req_line_speed == SPEED_100))) {
+                       if (vars->line_speed &&
+                           ((vars->line_speed == SPEED_10) ||
+                            (vars->line_speed == SPEED_100))) {
                                vars->phy_flags |= PHY_SGMII_FLAG;
                        } else {
                                vars->phy_flags &= ~PHY_SGMII_FLAG;
@@ -645,7 +645,7 @@ static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
        u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
                NIG_REG_INGRESS_BMAC0_MEM;
        u32 wb_data[2];
-    u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
+       u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
 
        /* Only if the bmac is out of reset */
        if (REG_RD(bp, MISC_REG_RESET_REG_2) &
@@ -670,7 +670,6 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
        u8 port = params->port;
        u32 init_crd, crd;
        u32 count = 1000;
-       u32 pause = 0;
 
        /* disable port */
        REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1);
@@ -693,33 +692,25 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
                return -EINVAL;
        }
 
-       if (flow_ctrl & FLOW_CTRL_RX)
-               pause = 1;
-       REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, pause);
-       if (pause) {
+       if (flow_ctrl & FLOW_CTRL_RX ||
+           line_speed == SPEED_10 ||
+           line_speed == SPEED_100 ||
+           line_speed == SPEED_1000 ||
+           line_speed == SPEED_2500) {
+               REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 1);
                /* update threshold */
                REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0);
                /* update init credit */
-               init_crd = 778;         /* (800-18-4) */
+               init_crd = 778;         /* (800-18-4) */
 
        } else {
                u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
                              ETH_OVREHEAD)/16;
-
+               REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
                /* update threshold */
                REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh);
                /* update init credit */
                switch (line_speed) {
-               case SPEED_10:
-               case SPEED_100:
-               case SPEED_1000:
-                       init_crd = thresh + 55 - 22;
-                       break;
-
-               case SPEED_2500:
-                       init_crd = thresh + 138 - 22;
-                       break;
-
                case SPEED_10000:
                        init_crd = thresh + 553 - 22;
                        break;
@@ -764,10 +755,10 @@ static u32 bnx2x_get_emac_base(u32 ext_phy_type, u8 port)
                emac_base = GRCBASE_EMAC0;
                break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-               emac_base = (port) ? GRCBASE_EMAC0: GRCBASE_EMAC1;
+               emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
                break;
        default:
-               emac_base = (port) ? GRCBASE_EMAC1: GRCBASE_EMAC0;
+               emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
                break;
        }
        return emac_base;
@@ -1044,7 +1035,7 @@ static void bnx2x_set_swap_lanes(struct link_params *params)
 }
 
 static void bnx2x_set_parallel_detection(struct link_params *params,
-                                      u8                phy_flags)
+                                      u8                phy_flags)
 {
        struct bnx2x *bp = params->bp;
        u16 control2;
@@ -1114,7 +1105,7 @@ static void bnx2x_set_autoneg(struct link_params *params,
                              MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
 
        /* CL37 Autoneg Enabled */
-       if (params->req_line_speed == SPEED_AUTO_NEG)
+       if (vars->line_speed == SPEED_AUTO_NEG)
                reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
        else /* CL37 Autoneg Disabled */
                reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
@@ -1132,7 +1123,7 @@ static void bnx2x_set_autoneg(struct link_params *params,
                              MDIO_REG_BANK_SERDES_DIGITAL,
                              MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
        reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN;
-       if (params->req_line_speed == SPEED_AUTO_NEG)
+       if (vars->line_speed == SPEED_AUTO_NEG)
                reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
        else
                reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
@@ -1148,7 +1139,7 @@ static void bnx2x_set_autoneg(struct link_params *params,
                              MDIO_REG_BANK_BAM_NEXT_PAGE,
                              MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
                          &reg_val);
-       if (params->req_line_speed == SPEED_AUTO_NEG) {
+       if (vars->line_speed == SPEED_AUTO_NEG) {
                /* Enable BAM aneg Mode and TetonII aneg Mode */
                reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
                            MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
@@ -1164,7 +1155,7 @@ static void bnx2x_set_autoneg(struct link_params *params,
                              reg_val);
 
        /* Enable Clause 73 Aneg */
-       if ((params->req_line_speed == SPEED_AUTO_NEG) &&
+       if ((vars->line_speed == SPEED_AUTO_NEG) &&
            (SUPPORT_CL73)) {
                /* Enable BAM Station Manager */
 
@@ -1226,7 +1217,8 @@ static void bnx2x_set_autoneg(struct link_params *params,
 }
 
 /* program SerDes, forced speed */
-static void bnx2x_program_serdes(struct link_params *params)
+static void bnx2x_program_serdes(struct link_params *params,
+                              struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
        u16 reg_val;
@@ -1248,28 +1240,35 @@ static void bnx2x_program_serdes(struct link_params *params)
 
        /* program speed
           - needed only if the speed is greater than 1G (2.5G or 10G) */
-       if (!((params->req_line_speed == SPEED_1000) ||
-             (params->req_line_speed == SPEED_100) ||
-             (params->req_line_speed == SPEED_10))) {
-               CL45_RD_OVER_CL22(bp, params->port,
+       CL45_RD_OVER_CL22(bp, params->port,
                                      params->phy_addr,
                                      MDIO_REG_BANK_SERDES_DIGITAL,
                                      MDIO_SERDES_DIGITAL_MISC1, &reg_val);
-               /* clearing the speed value before setting the right speed */
-               reg_val &= ~MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK;
+       /* clearing the speed value before setting the right speed */
+       DP(NETIF_MSG_LINK, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val);
+
+       reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK |
+                    MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
+
+       if (!((vars->line_speed == SPEED_1000) ||
+             (vars->line_speed == SPEED_100) ||
+             (vars->line_speed == SPEED_10))) {
+
                reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
                            MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
-               if (params->req_line_speed == SPEED_10000)
+               if (vars->line_speed == SPEED_10000)
                        reg_val |=
                                MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
-               if (params->req_line_speed == SPEED_13000)
+               if (vars->line_speed == SPEED_13000)
                        reg_val |=
                                MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
-               CL45_WR_OVER_CL22(bp, params->port,
+       }
+
+       CL45_WR_OVER_CL22(bp, params->port,
                                      params->phy_addr,
                                      MDIO_REG_BANK_SERDES_DIGITAL,
                                      MDIO_SERDES_DIGITAL_MISC1, reg_val);
-       }
+
 }
 
 static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
@@ -1295,48 +1294,49 @@ static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
                              MDIO_OVER_1G_UP3, 0);
 }
 
-static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
-                                          u32 *ieee_fc)
+static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc)
 {
-       struct bnx2x *bp = params->bp;
-       /* for AN, we are always publishing full duplex */
-       u16 an_adv = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
-
+       *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
        /* resolve pause mode and advertisement
         * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
 
        switch (params->req_flow_ctrl) {
        case FLOW_CTRL_AUTO:
-               if (params->mtu <= MAX_MTU_SIZE) {
-                       an_adv |=
+               if (params->req_fc_auto_adv == FLOW_CTRL_BOTH) {
+                       *ieee_fc |=
                             MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
                } else {
-                       an_adv |=
+                       *ieee_fc |=
                       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
                }
                break;
        case FLOW_CTRL_TX:
-               an_adv |=
+               *ieee_fc |=
                       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
                break;
 
        case FLOW_CTRL_RX:
        case FLOW_CTRL_BOTH:
-               an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+               *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
                break;
 
        case FLOW_CTRL_NONE:
        default:
-               an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
+               *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
                break;
        }
+}
 
-       *ieee_fc = an_adv;
+static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
+                                          u32 ieee_fc)
+{
+       struct bnx2x *bp = params->bp;
+       /* for AN, we are always publishing full duplex */
 
        CL45_WR_OVER_CL22(bp, params->port,
                              params->phy_addr,
                              MDIO_REG_BANK_COMBO_IEEE0,
-                             MDIO_COMBO_IEEE0_AUTO_NEG_ADV, an_adv);
+                             MDIO_COMBO_IEEE0_AUTO_NEG_ADV, (u16)ieee_fc);
 }
 
 static void bnx2x_restart_autoneg(struct link_params *params)
@@ -1382,7 +1382,8 @@ static void bnx2x_restart_autoneg(struct link_params *params)
        }
 }
 
-static void bnx2x_initialize_sgmii_process(struct link_params *params)
+static void bnx2x_initialize_sgmii_process(struct link_params *params,
+                                        struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
        u16 control1;
@@ -1406,7 +1407,7 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params)
                              control1);
 
        /* if forced speed */
-       if (!(params->req_line_speed == SPEED_AUTO_NEG)) {
+       if (!(vars->line_speed == SPEED_AUTO_NEG)) {
                /* set speed, disable autoneg */
                u16 mii_control;
 
@@ -1419,7 +1420,7 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params)
                                 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
                                 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);
 
-               switch (params->req_line_speed) {
+               switch (vars->line_speed) {
                case SPEED_100:
                        mii_control |=
                                MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100;
@@ -1433,8 +1434,8 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params)
                        break;
                default:
                        /* invalid speed for SGMII */
-                       DP(NETIF_MSG_LINK, "Invalid req_line_speed 0x%x\n",
-                                 params->req_line_speed);
+                       DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
+                                 vars->line_speed);
                        break;
                }
 
@@ -1460,20 +1461,20 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params)
  */
 
 static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
-{
-       switch (pause_result) {                 /* ASYM P ASYM P */
-       case 0xb:                               /*   1  0   1  1 */
+{                                              /*  LD      LP   */
+       switch (pause_result) {                 /* ASYM P ASYM P */
+       case 0xb:                               /*   1  0   1  1 */
                vars->flow_ctrl = FLOW_CTRL_TX;
                break;
 
-       case 0xe:                               /*   1  1   1  0 */
+       case 0xe:                               /*   1  1   1  0 */
                vars->flow_ctrl = FLOW_CTRL_RX;
                break;
 
-       case 0x5:                               /*   0  1   0  1 */
-       case 0x7:                               /*   0  1   1  1 */
-       case 0xd:                               /*   1  1   0  1 */
-       case 0xf:                               /*   1  1   1  1 */
+       case 0x5:                               /*   0  1   0  1 */
+       case 0x7:                               /*   0  1   1  1 */
+       case 0xd:                               /*   1  1   0  1 */
+       case 0xf:                               /*   1  1   1  1 */
                vars->flow_ctrl = FLOW_CTRL_BOTH;
                break;
 
@@ -1531,6 +1532,28 @@ static u8 bnx2x_ext_phy_resove_fc(struct link_params *params,
                DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n",
                   pause_result);
                bnx2x_pause_resolve(vars, pause_result);
+               if (vars->flow_ctrl == FLOW_CTRL_NONE &&
+                    ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
+                       bnx2x_cl45_read(bp, port,
+                                     ext_phy_type,
+                                     ext_phy_addr,
+                                     MDIO_AN_DEVAD,
+                                     MDIO_AN_REG_CL37_FC_LD, &ld_pause);
+
+                       bnx2x_cl45_read(bp, port,
+                                     ext_phy_type,
+                                     ext_phy_addr,
+                                     MDIO_AN_DEVAD,
+                                     MDIO_AN_REG_CL37_FC_LP, &lp_pause);
+                       pause_result = (ld_pause &
+                               MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
+                       pause_result |= (lp_pause &
+                               MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
+
+                       bnx2x_pause_resolve(vars, pause_result);
+                       DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x \n",
+                                pause_result);
+               }
        }
        return ret;
 }
@@ -1541,8 +1564,8 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
                                  u32 gp_status)
 {
        struct bnx2x *bp = params->bp;
-       u16 ld_pause;   /* local driver */
-       u16 lp_pause;   /* link partner */
+       u16 ld_pause;   /* local driver */
+       u16 lp_pause;   /* link partner */
        u16 pause_result;
 
        vars->flow_ctrl = FLOW_CTRL_NONE;
@@ -1573,13 +1596,10 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
                   (bnx2x_ext_phy_resove_fc(params, vars))) {
                return;
        } else {
-               vars->flow_ctrl = params->req_flow_ctrl;
-               if (vars->flow_ctrl == FLOW_CTRL_AUTO) {
-                       if (params->mtu <= MAX_MTU_SIZE)
-                               vars->flow_ctrl = FLOW_CTRL_BOTH;
-                       else
-                               vars->flow_ctrl = FLOW_CTRL_TX;
-               }
+               if (params->req_flow_ctrl == FLOW_CTRL_AUTO)
+                       vars->flow_ctrl = params->req_fc_auto_adv;
+               else
+                       vars->flow_ctrl = params->req_flow_ctrl;
        }
        DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
 }
@@ -1590,6 +1610,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
                                      u32 gp_status)
 {
        struct bnx2x *bp = params->bp;
+
        u8 rc = 0;
        vars->link_status = 0;
 
@@ -1690,7 +1711,11 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
 
                vars->link_status |= LINK_STATUS_SERDES_LINK;
 
-               if (params->req_line_speed == SPEED_AUTO_NEG) {
+               if ((params->req_line_speed == SPEED_AUTO_NEG) &&
+                   ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
+                    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
+                   (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
+                    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705))) {
                        vars->autoneg = AUTO_NEG_ENABLED;
 
                        if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
@@ -1705,18 +1730,18 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
 
                }
                if (vars->flow_ctrl & FLOW_CTRL_TX)
-                      vars->link_status |=
-                       LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
+                       vars->link_status |=
+                               LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
 
                if (vars->flow_ctrl & FLOW_CTRL_RX)
-                      vars->link_status |=
-                       LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
+                       vars->link_status |=
+                               LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
 
        } else { /* link_down */
                DP(NETIF_MSG_LINK, "phy link down\n");
 
                vars->phy_link_up = 0;
-               vars->line_speed = 0;
+
                vars->duplex = DUPLEX_FULL;
                vars->flow_ctrl = FLOW_CTRL_NONE;
                vars->autoneg = AUTO_NEG_DISABLED;
@@ -1817,15 +1842,15 @@ static u8 bnx2x_emac_program(struct link_params *params,
 }
 
 /*****************************************************************************/
-/*                           External Phy section                            */
+/*                          External Phy section                            */
 /*****************************************************************************/
-static void bnx2x_hw_reset(struct bnx2x *bp)
+static void bnx2x_hw_reset(struct bnx2x *bp, u8 port)
 {
        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-                      MISC_REGISTERS_GPIO_OUTPUT_LOW);
+                      MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
        msleep(1);
        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-                     MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+                     MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
 }
 
 static void bnx2x_ext_phy_reset(struct link_params *params,
@@ -1854,10 +1879,11 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
 
                        /* Restore normal power mode*/
                        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+                                         params->port);
 
                        /* HW reset */
-                       bnx2x_hw_reset(bp);
+                       bnx2x_hw_reset(bp, params->port);
 
                        bnx2x_cl45_write(bp, params->port,
                                       ext_phy_type,
@@ -1869,7 +1895,8 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
                        /* Unset Low Power Mode and SW reset */
                        /* Restore normal power mode*/
                        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+                                         params->port);
 
                        DP(NETIF_MSG_LINK, "XGXS 8072\n");
                        bnx2x_cl45_write(bp, params->port,
@@ -1887,19 +1914,14 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
 
                        /* Restore normal power mode*/
                        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+                                         params->port);
 
                        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+                                         params->port);
 
                        DP(NETIF_MSG_LINK, "XGXS 8073\n");
-                       bnx2x_cl45_write(bp,
-                                      params->port,
-                                      ext_phy_type,
-                                      ext_phy_addr,
-                                      MDIO_PMA_DEVAD,
-                                      MDIO_PMA_REG_CTRL,
-                                      1<<15);
                        }
                        break;
 
@@ -1908,10 +1930,11 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
 
                        /* Restore normal power mode*/
                        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+                                         params->port);
 
                        /* HW reset */
-                       bnx2x_hw_reset(bp);
+                       bnx2x_hw_reset(bp, params->port);
 
                        break;
 
@@ -1934,7 +1957,7 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
 
                case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
                        DP(NETIF_MSG_LINK, "SerDes 5482\n");
-                       bnx2x_hw_reset(bp);
+                       bnx2x_hw_reset(bp, params->port);
                        break;
 
                default:
@@ -2098,42 +2121,45 @@ static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
 
 }
 
-static void bnx2x_bcm8073_external_rom_boot(struct link_params *params)
+static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
+                                         u8 ext_phy_addr)
 {
-       struct bnx2x *bp = params->bp;
-       u8 port = params->port;
-       u8 ext_phy_addr = ((params->ext_phy_config &
-                            PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
-                           PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
-       u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-       u16 fw_ver1, fw_ver2, val;
-       /* Need to wait 100ms after reset */
-       msleep(100);
-       /* Boot port from external ROM  */
+       u16 fw_ver1, fw_ver2;
+       /* Boot port from external ROM  */
        /* EDC grst */
-       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+       bnx2x_cl45_write(bp, port,
+                      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                      ext_phy_addr,
                       MDIO_PMA_DEVAD,
                       MDIO_PMA_REG_GEN_CTRL,
                       0x0001);
 
        /* ucode reboot and rst */
-       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+       bnx2x_cl45_write(bp, port,
+                      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                      ext_phy_addr,
                       MDIO_PMA_DEVAD,
                       MDIO_PMA_REG_GEN_CTRL,
                       0x008c);
 
-       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+       bnx2x_cl45_write(bp, port,
+                      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                      ext_phy_addr,
                       MDIO_PMA_DEVAD,
                       MDIO_PMA_REG_MISC_CTRL1, 0x0001);
 
        /* Reset internal microprocessor */
-       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+       bnx2x_cl45_write(bp, port,
+                      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                      ext_phy_addr,
                       MDIO_PMA_DEVAD,
                       MDIO_PMA_REG_GEN_CTRL,
                       MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
 
        /* Release srst bit */
-       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+       bnx2x_cl45_write(bp, port,
+                      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                      ext_phy_addr,
                       MDIO_PMA_DEVAD,
                       MDIO_PMA_REG_GEN_CTRL,
                       MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
@@ -2142,35 +2168,52 @@ static void bnx2x_bcm8073_external_rom_boot(struct link_params *params)
        msleep(100);
 
        /* Clear ser_boot_ctl bit */
-       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+       bnx2x_cl45_write(bp, port,
+                      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                      ext_phy_addr,
                       MDIO_PMA_DEVAD,
                       MDIO_PMA_REG_MISC_CTRL1, 0x0000);
 
-       bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
-                      MDIO_PMA_DEVAD,
-                      MDIO_PMA_REG_ROM_VER1, &fw_ver1);
-       bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
-                      MDIO_PMA_DEVAD,
-                      MDIO_PMA_REG_ROM_VER2, &fw_ver2);
+       bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                     ext_phy_addr,
+                     MDIO_PMA_DEVAD,
+                     MDIO_PMA_REG_ROM_VER1, &fw_ver1);
+       bnx2x_cl45_read(bp, port,
+                     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                     ext_phy_addr,
+                     MDIO_PMA_DEVAD,
+                     MDIO_PMA_REG_ROM_VER2, &fw_ver2);
        DP(NETIF_MSG_LINK, "8073 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
 
-       /* Only set bit 10 = 1 (Tx power down) */
-       bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
-                      MDIO_PMA_DEVAD,
-                      MDIO_PMA_REG_TX_POWER_DOWN, &val);
+}
+
+static void bnx2x_bcm807x_force_10G(struct link_params *params)
+{
+       struct bnx2x *bp = params->bp;
+       u8 port = params->port;
+       u8 ext_phy_addr = ((params->ext_phy_config &
+                               PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
+                               PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+       u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
 
+       /* Force KR or KX */
        bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
                       MDIO_PMA_DEVAD,
-                      MDIO_PMA_REG_TX_POWER_DOWN, (val | 1<<10));
-
-       msleep(600);
-       /* Release bit 10 (Release Tx power down) */
+                      MDIO_PMA_REG_CTRL,
+                      0x2040);
        bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
                       MDIO_PMA_DEVAD,
-                      MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
-
+                      MDIO_PMA_REG_10G_CTRL2,
+                      0x000b);
+       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+                      MDIO_PMA_DEVAD,
+                      MDIO_PMA_REG_BCM_CTRL,
+                      0x0000);
+       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+                      MDIO_AN_DEVAD,
+                      MDIO_AN_REG_CTRL,
+                      0x0000);
 }
-
 static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
@@ -2236,32 +2279,51 @@ static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
        bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
                       MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
 }
-static void bnx2x_bcm807x_force_10G(struct link_params *params)
+
+static void bnx2x_8073_set_pause_cl37(struct link_params *params,
+                                 struct link_vars *vars)
 {
+
        struct bnx2x *bp = params->bp;
-       u8 port = params->port;
+       u16 cl37_val;
        u8 ext_phy_addr = ((params->ext_phy_config &
                                PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
                                PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
        u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
 
-       /* Force KR or KX */
-       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-                      MDIO_PMA_DEVAD,
-                      MDIO_PMA_REG_CTRL,
-                      0x2040);
-       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-                      MDIO_PMA_DEVAD,
-                      MDIO_PMA_REG_10G_CTRL2,
-                      0x000b);
-       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-                      MDIO_PMA_DEVAD,
-                      MDIO_PMA_REG_BCM_CTRL,
-                      0x0000);
-       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+       bnx2x_cl45_read(bp, params->port,
+                     ext_phy_type,
+                     ext_phy_addr,
+                     MDIO_AN_DEVAD,
+                     MDIO_AN_REG_CL37_FC_LD, &cl37_val);
+
+       cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+       /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+
+       if ((vars->ieee_fc &
+           MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
+           MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
+               cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
+       }
+       if ((vars->ieee_fc &
+           MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+           MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
+               cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+       }
+       if ((vars->ieee_fc &
+           MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+           MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
+               cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+       }
+       DP(NETIF_MSG_LINK,
+                "Ext phy AN advertize cl37 0x%x\n", cl37_val);
+
+       bnx2x_cl45_write(bp, params->port,
+                      ext_phy_type,
+                      ext_phy_addr,
                       MDIO_AN_DEVAD,
-                      MDIO_AN_REG_CTRL,
-                      0x0000);
+                      MDIO_AN_REG_CL37_FC_LD, cl37_val);
+       msleep(500);
 }
 
 static void bnx2x_ext_phy_set_pause(struct link_params *params,
@@ -2282,13 +2344,16 @@ static void bnx2x_ext_phy_set_pause(struct link_params *params,
                      MDIO_AN_REG_ADV_PAUSE, &val);
 
        val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
+
        /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
 
-       if (vars->ieee_fc &
+       if ((vars->ieee_fc &
+           MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
            MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
                val |=  MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
        }
-       if (vars->ieee_fc &
+       if ((vars->ieee_fc &
+           MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
            MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
                val |=
                 MDIO_AN_REG_ADV_PAUSE_PAUSE;
@@ -2302,6 +2367,65 @@ static void bnx2x_ext_phy_set_pause(struct link_params *params,
                       MDIO_AN_REG_ADV_PAUSE, val);
 }
 
+
+static void bnx2x_init_internal_phy(struct link_params *params,
+                               struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       u8 port = params->port;
+       if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
+               u16 bank, rx_eq;
+
+               rx_eq = ((params->serdes_config &
+                         PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK) >>
+                        PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT);
+
+               DP(NETIF_MSG_LINK, "setting rx eq to 0x%x\n", rx_eq);
+               for (bank = MDIO_REG_BANK_RX0; bank <= MDIO_REG_BANK_RX_ALL;
+                     bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0)) {
+                       CL45_WR_OVER_CL22(bp, port,
+                                             params->phy_addr,
+                                             bank ,
+                                             MDIO_RX0_RX_EQ_BOOST,
+                                             ((rx_eq &
+                               MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK) |
+                               MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL));
+               }
+
+               /* forced speed requested? */
+               if (vars->line_speed != SPEED_AUTO_NEG) {
+                       DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
+
+                       /* disable autoneg */
+                       bnx2x_set_autoneg(params, vars);
+
+                       /* program speed and duplex */
+                       bnx2x_program_serdes(params, vars);
+
+               } else { /* AN_mode */
+                       DP(NETIF_MSG_LINK, "not SGMII, AN\n");
+
+                       /* AN enabled */
+                       bnx2x_set_brcm_cl37_advertisment(params);
+
+                       /* program duplex & pause advertisement (for aneg) */
+                       bnx2x_set_ieee_aneg_advertisment(params,
+                                                      vars->ieee_fc);
+
+                       /* enable autoneg */
+                       bnx2x_set_autoneg(params, vars);
+
+                       /* enable and restart AN */
+                       bnx2x_restart_autoneg(params);
+               }
+
+       } else { /* SGMII mode */
+               DP(NETIF_MSG_LINK, "SGMII\n");
+
+               bnx2x_initialize_sgmii_process(params, vars);
+       }
+}
+
 static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
@@ -2343,7 +2467,6 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
 
                switch (ext_phy_type) {
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-                       DP(NETIF_MSG_LINK, "XGXS Direct\n");
                        break;
 
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
@@ -2419,7 +2542,7 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
                                               ext_phy_type,
                                               ext_phy_addr,
                                               MDIO_AN_DEVAD,
-                                              MDIO_AN_REG_CL37_FD,
+                                              MDIO_AN_REG_CL37_FC_LP,
                                               0x0020);
                                /* Enable CL37 AN */
                                bnx2x_cl45_write(bp, params->port,
@@ -2458,54 +2581,43 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
                                rx_alarm_ctrl_val = 0x400;
                                lasi_ctrl_val = 0x0004;
                        } else {
-                               /* In 8073, port1 is directed through emac0 and
-                                * port0 is directed through emac1
-                                */
                                rx_alarm_ctrl_val = (1<<2);
-                               /*lasi_ctrl_val = 0x0005;*/
                                lasi_ctrl_val = 0x0004;
                        }
 
-                       /* Wait for soft reset to get cleared upto 1 sec */
-                       for (cnt = 0; cnt < 1000; cnt++) {
-                               bnx2x_cl45_read(bp, params->port,
-                                             ext_phy_type,
-                                             ext_phy_addr,
-                                             MDIO_PMA_DEVAD,
-                                             MDIO_PMA_REG_CTRL,
-                                             &ctrl);
-                               if (!(ctrl & (1<<15)))
-                                       break;
-                               msleep(1);
-                       }
-                       DP(NETIF_MSG_LINK,
-                               "807x control reg 0x%x (after %d ms)\n",
-                               ctrl, cnt);
+                       /* enable LASI */
+                       bnx2x_cl45_write(bp, params->port,
+                                  ext_phy_type,
+                                  ext_phy_addr,
+                                  MDIO_PMA_DEVAD,
+                                  MDIO_PMA_REG_RX_ALARM_CTRL,
+                                  rx_alarm_ctrl_val);
+
+                       bnx2x_cl45_write(bp, params->port,
+                                      ext_phy_type,
+                                      ext_phy_addr,
+                                      MDIO_PMA_DEVAD,
+                                      MDIO_PMA_REG_LASI_CTRL,
+                                      lasi_ctrl_val);
+
+                       bnx2x_8073_set_pause_cl37(params, vars);
 
                        if (ext_phy_type ==
                            PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072){
                                bnx2x_bcm8072_external_rom_boot(params);
                        } else {
-                               bnx2x_bcm8073_external_rom_boot(params);
+
                                /* In case of 8073 with long xaui lines,
                                don't set the 8073 xaui low power*/
                                bnx2x_bcm8073_set_xaui_low_power_mode(params);
                        }
 
-                       /* enable LASI */
-                       bnx2x_cl45_write(bp, params->port,
-                                      ext_phy_type,
-                                      ext_phy_addr,
-                                      MDIO_PMA_DEVAD,
-                                      MDIO_PMA_REG_RX_ALARM_CTRL,
-                                      rx_alarm_ctrl_val);
-
-                       bnx2x_cl45_write(bp, params->port,
-                                      ext_phy_type,
-                                      ext_phy_addr,
-                                      MDIO_PMA_DEVAD,
-                                      MDIO_PMA_REG_LASI_CTRL,
-                                      lasi_ctrl_val);
+                       bnx2x_cl45_read(bp, params->port,
+                                     ext_phy_type,
+                                     ext_phy_addr,
+                                     MDIO_PMA_DEVAD,
+                                     0xca13,
+                                     &tmp1);
 
                        bnx2x_cl45_read(bp, params->port,
                                      ext_phy_type,
@@ -2519,12 +2631,21 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
                        /* If this is forced speed, set to KR or KX
                         * (all other are not supported)
                         */
-                       if (!(params->req_line_speed == SPEED_AUTO_NEG)) {
-                       if (params->req_line_speed == SPEED_10000) {
-                                       bnx2x_bcm807x_force_10G(params);
-                                       DP(NETIF_MSG_LINK,
-                                          "Forced speed 10G on 807X\n");
-                                       break;
+                       if (params->loopback_mode == LOOPBACK_EXT) {
+                               bnx2x_bcm807x_force_10G(params);
+                               DP(NETIF_MSG_LINK,
+                                       "Forced speed 10G on 807X\n");
+                               break;
+                       } else {
+                               bnx2x_cl45_write(bp, params->port,
+                                              ext_phy_type, ext_phy_addr,
+                                              MDIO_PMA_DEVAD,
+                                              MDIO_PMA_REG_BCM_CTRL,
+                                              0x0002);
+                       }
+                       if (params->req_line_speed != SPEED_AUTO_NEG) {
+                               if (params->req_line_speed == SPEED_10000) {
+                                       val = (1<<7);
                                } else if (params->req_line_speed ==
                                           SPEED_2500) {
                                        val = (1<<5);
@@ -2539,11 +2660,14 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
                                        PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
                                        val |= (1<<7);
 
+                               /* Note that 2.5G works only when
+                               used with 1G advertisment */
                                if (params->speed_cap_mask &
-                                       PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
+                                       (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
+                                        PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
                                        val |= (1<<5);
-                               DP(NETIF_MSG_LINK, "807x autoneg val = 0x%x\n", val);
-                               /*val = ((1<<5)|(1<<7));*/
+                               DP(NETIF_MSG_LINK,
+                                        "807x autoneg val = 0x%x\n", val);
                        }
 
                        bnx2x_cl45_write(bp, params->port,
@@ -2554,20 +2678,19 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
 
                        if (ext_phy_type ==
                            PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-                               /* Disable 2.5Ghz */
+
                                bnx2x_cl45_read(bp, params->port,
                                              ext_phy_type,
                                              ext_phy_addr,
                                              MDIO_AN_DEVAD,
                                              0x8329, &tmp1);
-/* SUPPORT_SPEED_CAPABILITY
-                               (Due to the nature of the link order, its not
-                               possible to enable 2.5G within the autoneg
-                               capabilities)
-                               if (params->speed_cap_mask &
-                               PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
-*/
-                               if (params->req_line_speed == SPEED_2500) {
+
+                               if (((params->speed_cap_mask &
+                                     PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
+                                    (params->req_line_speed ==
+                                     SPEED_AUTO_NEG)) ||
+                                   (params->req_line_speed ==
+                                    SPEED_2500)) {
                                        u16 phy_ver;
                                        /* Allow 2.5G for A1 and above */
                                        bnx2x_cl45_read(bp, params->port,
@@ -2575,49 +2698,53 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
                                         ext_phy_addr,
                                         MDIO_PMA_DEVAD,
                                         0xc801, &phy_ver);
-
+                                       DP(NETIF_MSG_LINK, "Add 2.5G\n");
                                        if (phy_ver > 0)
                                                tmp1 |= 1;
                                        else
                                                tmp1 &= 0xfffe;
-                       }
-                               else
+                               } else {
+                                       DP(NETIF_MSG_LINK, "Disable 2.5G\n");
                                        tmp1 &= 0xfffe;
+                               }
 
-                       bnx2x_cl45_write(bp, params->port,
-                                      ext_phy_type,
-                                      ext_phy_addr,
-                                      MDIO_AN_DEVAD,
+                               bnx2x_cl45_write(bp, params->port,
+                                              ext_phy_type,
+                                              ext_phy_addr,
+                                              MDIO_AN_DEVAD,
                                               0x8329, tmp1);
                        }
-                       /* Add support for CL37 (passive mode) I */
-                       bnx2x_cl45_write(bp, params->port,
+
+                       /* Add support for CL37 (passive mode) II */
+
+                       bnx2x_cl45_read(bp, params->port,
                                       ext_phy_type,
                                       ext_phy_addr,
                                       MDIO_AN_DEVAD,
-                                      MDIO_AN_REG_CL37_CL73, 0x040c);
-                       /* Add support for CL37 (passive mode) II */
+                                      MDIO_AN_REG_CL37_FC_LD,
+                                      &tmp1);
+
                        bnx2x_cl45_write(bp, params->port,
                                       ext_phy_type,
                                       ext_phy_addr,
                                       MDIO_AN_DEVAD,
-                                      MDIO_AN_REG_CL37_FD, 0x20);
+                                      MDIO_AN_REG_CL37_FC_LD, (tmp1 |
+                                      ((params->req_duplex == DUPLEX_FULL) ?
+                                      0x20 : 0x40)));
+
                        /* Add support for CL37 (passive mode) III */
                        bnx2x_cl45_write(bp, params->port,
                                       ext_phy_type,
                                       ext_phy_addr,
                                       MDIO_AN_DEVAD,
                                       MDIO_AN_REG_CL37_AN, 0x1000);
-                       /* Restart autoneg */
-                       msleep(500);
 
                        if (ext_phy_type ==
                            PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-
-                       /* The SNR will improve about 2db by changing the
+                               /* The SNR will improve about 2db by changing
                                BW and FEE main tap. Rest commands are executed
                                after link is up*/
-                       /* Change FFE main cursor to 5 in EDC register */
+                               /*Change FFE main cursor to 5 in EDC register*/
                                if (bnx2x_8073_is_snr_needed(params))
                                        bnx2x_cl45_write(bp, params->port,
                                                    ext_phy_type,
@@ -2626,25 +2753,28 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
                                                    MDIO_PMA_REG_EDC_FFE_MAIN,
                                                    0xFB0C);
 
-                       /* Enable FEC (Forware Error Correction)
-                          Request in the AN */
-                       bnx2x_cl45_read(bp, params->port,
-                                     ext_phy_type,
-                                     ext_phy_addr,
-                                     MDIO_AN_DEVAD,
-                                     MDIO_AN_REG_ADV2, &tmp1);
+                               /* Enable FEC (Forware Error Correction)
+                               Request in the AN */
+                               bnx2x_cl45_read(bp, params->port,
+                                             ext_phy_type,
+                                             ext_phy_addr,
+                                             MDIO_AN_DEVAD,
+                                             MDIO_AN_REG_ADV2, &tmp1);
 
-                       tmp1 |= (1<<15);
+                               tmp1 |= (1<<15);
+
+                               bnx2x_cl45_write(bp, params->port,
+                                              ext_phy_type,
+                                              ext_phy_addr,
+                                              MDIO_AN_DEVAD,
+                                              MDIO_AN_REG_ADV2, tmp1);
 
-                       bnx2x_cl45_write(bp, params->port,
-                                     ext_phy_type,
-                                     ext_phy_addr,
-                                     MDIO_AN_DEVAD,
-                                     MDIO_AN_REG_ADV2, tmp1);
                        }
 
                        bnx2x_ext_phy_set_pause(params, vars);
 
+                       /* Restart autoneg */
+                       msleep(500);
                        bnx2x_cl45_write(bp, params->port,
                                       ext_phy_type,
                                       ext_phy_addr,
@@ -2701,10 +2831,7 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
                }
 
        } else { /* SerDes */
-/*             ext_phy_addr = ((bp->ext_phy_config &
-                                PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK) >>
-                               PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT);
-*/
+
                ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
                switch (ext_phy_type) {
                case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
@@ -2726,7 +2853,7 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
 
 
 static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
-                                 struct link_vars *vars)
+                                struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
        u32 ext_phy_type;
@@ -2767,6 +2894,8 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
                                      MDIO_PMA_REG_RX_SD, &rx_sd);
                        DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd);
                        ext_phy_link_up = (rx_sd & 0x1);
+                       if (ext_phy_link_up)
+                               vars->line_speed = SPEED_10000;
                        break;
 
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
@@ -2810,6 +2939,13 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
                         */
                        ext_phy_link_up = ((rx_sd & pcs_status & 0x1) ||
                                           (val2 & (1<<1)));
+                       if (ext_phy_link_up) {
+                               if (val2 & (1<<1))
+                                       vars->line_speed = SPEED_1000;
+                               else
+                                       vars->line_speed = SPEED_10000;
+                       }
+
                        /* clear LASI indication*/
                        bnx2x_cl45_read(bp, params->port, ext_phy_type,
                                      ext_phy_addr,
@@ -2820,6 +2956,8 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
                {
+                       u16 link_status = 0;
+                       u16 an1000_status = 0;
                        if (ext_phy_type ==
                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
                                bnx2x_cl45_read(bp, params->port,
@@ -2846,14 +2984,9 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
                                              MDIO_PMA_DEVAD,
                                              MDIO_PMA_REG_LASI_STATUS, &val1);
 
-                               bnx2x_cl45_read(bp, params->port,
-                                             ext_phy_type,
-                                             ext_phy_addr,
-                                             MDIO_PMA_DEVAD,
-                                             MDIO_PMA_REG_LASI_STATUS, &val2);
                                DP(NETIF_MSG_LINK,
-                                        "8703 LASI status 0x%x->0x%x\n",
-                                         val1, val2);
+                                        "8703 LASI status 0x%x\n",
+                                         val1);
                        }
 
                        /* clear the interrupt LASI status register */
@@ -2869,20 +3002,23 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
                                      MDIO_PCS_REG_STATUS, &val1);
                        DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n",
                           val2, val1);
-                       /* Check the LASI */
+                       /* Clear MSG-OUT */
                        bnx2x_cl45_read(bp, params->port,
                                      ext_phy_type,
                                      ext_phy_addr,
                                      MDIO_PMA_DEVAD,
-                                     MDIO_PMA_REG_RX_ALARM, &val2);
+                                     0xca13,
+                                     &val1);
+
+                       /* Check the LASI */
                        bnx2x_cl45_read(bp, params->port,
                                      ext_phy_type,
                                      ext_phy_addr,
                                      MDIO_PMA_DEVAD,
-                                     MDIO_PMA_REG_RX_ALARM,
-                                     &val1);
-                       DP(NETIF_MSG_LINK, "KR 0x9003 0x%x->0x%x\n",
-                          val2, val1);
+                                     MDIO_PMA_REG_RX_ALARM, &val2);
+
+                       DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
+
                        /* Check the link status */
                        bnx2x_cl45_read(bp, params->port,
                                      ext_phy_type,
@@ -2905,29 +3041,29 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
                        DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
                        if (ext_phy_type ==
                            PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-                               u16 an1000_status = 0;
+
                                if (ext_phy_link_up &&
-                                   (
-                                    (params->req_line_speed != SPEED_10000)
-                                    )) {
+                                   ((params->req_line_speed !=
+                                       SPEED_10000))) {
                                        if (bnx2x_bcm8073_xaui_wa(params)
                                             != 0) {
                                                ext_phy_link_up = 0;
                                                break;
                                        }
-                                       bnx2x_cl45_read(bp, params->port,
+                               }
+                               bnx2x_cl45_read(bp, params->port,
                                                      ext_phy_type,
                                                      ext_phy_addr,
-                                                     MDIO_XS_DEVAD,
+                                                     MDIO_AN_DEVAD,
                                                      0x8304,
                                                      &an1000_status);
-                                       bnx2x_cl45_read(bp, params->port,
+                               bnx2x_cl45_read(bp, params->port,
                                                      ext_phy_type,
                                                      ext_phy_addr,
-                                                     MDIO_XS_DEVAD,
+                                                     MDIO_AN_DEVAD,
                                                      0x8304,
                                                      &an1000_status);
-                               }
+
                                /* Check the link status on 1.1.2 */
                                bnx2x_cl45_read(bp, params->port,
                                              ext_phy_type,
@@ -2943,8 +3079,8 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
                                             "an_link_status=0x%x\n",
                                          val2, val1, an1000_status);
 
-                               ext_phy_link_up = (((val1 & 4) == 4) ||
-                                                   (an1000_status & (1<<1)));
+                                       ext_phy_link_up = (((val1 & 4) == 4) ||
+                                               (an1000_status & (1<<1)));
                                if (ext_phy_link_up &&
                                    bnx2x_8073_is_snr_needed(params)) {
                                        /* The SNR will improve about 2dbby
@@ -2968,8 +3104,74 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
                                                    MDIO_PMA_REG_CDR_BANDWIDTH,
                                                    0x0333);
 
+
+                               }
+                               bnx2x_cl45_read(bp, params->port,
+                                                     ext_phy_type,
+                                                     ext_phy_addr,
+                                                     MDIO_PMA_DEVAD,
+                                                     0xc820,
+                                                     &link_status);
+
+                               /* Bits 0..2 --> speed detected,
+                                  bits 13..15--> link is down */
+                               if ((link_status & (1<<2)) &&
+                                   (!(link_status & (1<<15)))) {
+                                       ext_phy_link_up = 1;
+                                       vars->line_speed = SPEED_10000;
+                                       DP(NETIF_MSG_LINK,
+                                                "port %x: External link"
+                                                " up in 10G\n", params->port);
+                               } else if ((link_status & (1<<1)) &&
+                                          (!(link_status & (1<<14)))) {
+                                       ext_phy_link_up = 1;
+                                       vars->line_speed = SPEED_2500;
+                                       DP(NETIF_MSG_LINK,
+                                                "port %x: External link"
+                                                " up in 2.5G\n", params->port);
+                               } else if ((link_status & (1<<0)) &&
+                                          (!(link_status & (1<<13)))) {
+                                       ext_phy_link_up = 1;
+                                       vars->line_speed = SPEED_1000;
+                                       DP(NETIF_MSG_LINK,
+                                                "port %x: External link"
+                                                " up in 1G\n", params->port);
+                               } else {
+                                       ext_phy_link_up = 0;
+                                       DP(NETIF_MSG_LINK,
+                                                "port %x: External link"
+                                                " is down\n", params->port);
+                               }
+                       } else {
+                               /* See if 1G link is up for the 8072 */
+                               bnx2x_cl45_read(bp, params->port,
+                                                     ext_phy_type,
+                                                     ext_phy_addr,
+                                                     MDIO_AN_DEVAD,
+                                                     0x8304,
+                                                     &an1000_status);
+                               bnx2x_cl45_read(bp, params->port,
+                                                     ext_phy_type,
+                                                     ext_phy_addr,
+                                                     MDIO_AN_DEVAD,
+                                                     0x8304,
+                                                     &an1000_status);
+                               if (an1000_status & (1<<1)) {
+                                       ext_phy_link_up = 1;
+                                       vars->line_speed = SPEED_1000;
+                                       DP(NETIF_MSG_LINK,
+                                                "port %x: External link"
+                                                " up in 1G\n", params->port);
+                               } else if (ext_phy_link_up) {
+                                       ext_phy_link_up = 1;
+                                       vars->line_speed = SPEED_10000;
+                                       DP(NETIF_MSG_LINK,
+                                                "port %x: External link"
+                                                " up in 10G\n", params->port);
                                }
                        }
+
+
                        break;
                }
                case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
@@ -3006,6 +3208,7 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
                                              MDIO_AN_DEVAD,
                                              MDIO_AN_REG_MASTER_STATUS,
                                              &val2);
+                               vars->line_speed = SPEED_10000;
                                DP(NETIF_MSG_LINK,
                                         "SFX7101 AN status 0x%x->Master=%x\n",
                                          val2,
@@ -3100,7 +3303,7 @@ static void bnx2x_link_int_enable(struct link_params *params)
  * link management
  */
 static void bnx2x_link_int_ack(struct link_params *params,
-                            struct link_vars *vars, u16 is_10g)
+                            struct link_vars *vars, u8 is_10g)
 {
        struct bnx2x *bp = params->bp;
        u8 port = params->port;
@@ -3181,7 +3384,8 @@ static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
 }
 
 
-static void bnx2x_turn_on_sf(struct bnx2x *bp, u8 port, u8 ext_phy_addr)
+static void bnx2x_turn_on_ef(struct bnx2x *bp, u8 port, u8 ext_phy_addr,
+                          u32 ext_phy_type)
 {
        u32 cnt = 0;
        u16 ctrl = 0;
@@ -3192,12 +3396,14 @@ static void bnx2x_turn_on_sf(struct bnx2x *bp, u8 port, u8 ext_phy_addr)
 
        /* take ext phy out of reset */
        bnx2x_set_gpio(bp,
-                       MISC_REGISTERS_GPIO_2,
-                       MISC_REGISTERS_GPIO_HIGH);
+                         MISC_REGISTERS_GPIO_2,
+                         MISC_REGISTERS_GPIO_HIGH,
+                         port);
 
        bnx2x_set_gpio(bp,
-                       MISC_REGISTERS_GPIO_1,
-                       MISC_REGISTERS_GPIO_HIGH);
+                         MISC_REGISTERS_GPIO_1,
+                         MISC_REGISTERS_GPIO_HIGH,
+                         port);
 
        /* wait for 5ms */
        msleep(5);
@@ -3205,7 +3411,7 @@ static void bnx2x_turn_on_sf(struct bnx2x *bp, u8 port, u8 ext_phy_addr)
        for (cnt = 0; cnt < 1000; cnt++) {
                msleep(1);
                bnx2x_cl45_read(bp, port,
-                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
+                             ext_phy_type,
                              ext_phy_addr,
                              MDIO_PMA_DEVAD,
                              MDIO_PMA_REG_CTRL,
@@ -3217,13 +3423,17 @@ static void bnx2x_turn_on_sf(struct bnx2x *bp, u8 port, u8 ext_phy_addr)
        }
 }
 
-static void bnx2x_turn_off_sf(struct bnx2x *bp)
+static void bnx2x_turn_off_sf(struct bnx2x *bp, u8 port)
 {
        /* put sf to reset */
-       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_LOW);
        bnx2x_set_gpio(bp,
-                       MISC_REGISTERS_GPIO_2,
-                       MISC_REGISTERS_GPIO_LOW);
+                         MISC_REGISTERS_GPIO_1,
+                         MISC_REGISTERS_GPIO_LOW,
+                         port);
+       bnx2x_set_gpio(bp,
+                         MISC_REGISTERS_GPIO_2,
+                         MISC_REGISTERS_GPIO_LOW,
+                         port);
 }
 
 u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
@@ -3253,7 +3463,8 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
 
                /* Take ext phy out of reset */
                if (!driver_loaded)
-                       bnx2x_turn_on_sf(bp, params->port, ext_phy_addr);
+                       bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
+                                      ext_phy_type);
 
                /*  wait for 1ms */
                msleep(1);
@@ -3276,11 +3487,16 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
                version[4] = '\0';
 
                if (!driver_loaded)
-                       bnx2x_turn_off_sf(bp);
+                       bnx2x_turn_off_sf(bp, params->port);
                break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
        {
+               /* Take ext phy out of reset */
+               if (!driver_loaded)
+                       bnx2x_turn_on_ef(bp, params->port, ext_phy_addr,
+                                      ext_phy_type);
+
                bnx2x_cl45_read(bp, params->port, ext_phy_type,
                              ext_phy_addr,
                              MDIO_PMA_DEVAD,
@@ -3333,7 +3549,7 @@ static void bnx2x_set_xgxs_loopback(struct link_params *params,
        struct bnx2x *bp = params->bp;
 
        if (is_10g) {
-                u32 md_devad;
+               u32 md_devad;
 
                DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
 
@@ -3553,6 +3769,8 @@ u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
               u16 hw_led_mode, u32 chip_id)
 {
        u8 rc = 0;
+       u32 tmp;
+       u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
        DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
        DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
                 speed, hw_led_mode);
@@ -3561,6 +3779,9 @@ u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
                REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
                REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
                           SHARED_HW_CFG_LED_MAC1);
+
+               tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
+               EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
                break;
 
        case LED_MODE_OPER:
@@ -3572,6 +3793,10 @@ u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
                           LED_BLINK_RATE_VAL);
                REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
                           port*4, 1);
+               tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
+               EMAC_WR(bp, EMAC_REG_EMAC_LED,
+                           (tmp & (~EMAC_LED_OVERRIDE)));
+
                if (!CHIP_IS_E1H(bp) &&
                    ((speed == SPEED_2500) ||
                     (speed == SPEED_1000) ||
@@ -3622,7 +3847,8 @@ static u8 bnx2x_link_initialize(struct link_params *params,
        struct bnx2x *bp = params->bp;
        u8 port = params->port;
        u8 rc = 0;
-
+       u8 non_ext_phy;
+       u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
        /* Activate the external PHY */
        bnx2x_ext_phy_reset(params, vars);
 
@@ -3644,10 +3870,6 @@ static u8 bnx2x_link_initialize(struct link_params *params,
                bnx2x_set_swap_lanes(params);
        }
 
-       /* Set Parallel Detect */
-       if (params->req_line_speed == SPEED_AUTO_NEG)
-               bnx2x_set_parallel_detection(params, vars->phy_flags);
-
        if (vars->phy_flags & PHY_XGXS_FLAG) {
                if (params->req_line_speed &&
                    ((params->req_line_speed == SPEED_100) ||
@@ -3657,68 +3879,33 @@ static u8 bnx2x_link_initialize(struct link_params *params,
                        vars->phy_flags &= ~PHY_SGMII_FLAG;
                }
        }
+       /* In case of external phy existance, the line speed would be the
+        line speed linked up by the external phy. In case it is direct only,
+         then the line_speed during initialization will be equal to the
+          req_line_speed*/
+       vars->line_speed = params->req_line_speed;
 
-       if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
-               u16 bank, rx_eq;
-
-               rx_eq = ((params->serdes_config &
-                         PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK) >>
-                        PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT);
-
-               DP(NETIF_MSG_LINK, "setting rx eq to 0x%x\n", rx_eq);
-               for (bank = MDIO_REG_BANK_RX0; bank <= MDIO_REG_BANK_RX_ALL;
-                     bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0)) {
-                       CL45_WR_OVER_CL22(bp, port,
-                                             params->phy_addr,
-                                             bank ,
-                                             MDIO_RX0_RX_EQ_BOOST,
-                                             ((rx_eq &
-                               MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK) |
-                               MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL));
-               }
-
-               /* forced speed requested? */
-               if (params->req_line_speed != SPEED_AUTO_NEG) {
-                       DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
-
-                       /* disable autoneg */
-                       bnx2x_set_autoneg(params, vars);
-
-                       /* program speed and duplex */
-                       bnx2x_program_serdes(params);
-                       vars->ieee_fc =
-                               MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
-
-               } else { /* AN_mode */
-                       DP(NETIF_MSG_LINK, "not SGMII, AN\n");
+       bnx2x_calc_ieee_aneg_adv(params, &vars->ieee_fc);
 
-                       /* AN enabled */
-                       bnx2x_set_brcm_cl37_advertisment(params);
-
-                       /* program duplex & pause advertisement (for aneg) */
-                       bnx2x_set_ieee_aneg_advertisment(params,
-                                                      &vars->ieee_fc);
-
-                       /* enable autoneg */
-                       bnx2x_set_autoneg(params, vars);
-
-                       /* enable and restart AN */
-                       bnx2x_restart_autoneg(params);
-               }
-
-       } else { /* SGMII mode */
-               DP(NETIF_MSG_LINK, "SGMII\n");
-
-               bnx2x_initialize_sgmii_process(params);
+       /* init ext phy and enable link state int */
+       non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
+                      (params->loopback_mode == LOOPBACK_XGXS_10) ||
+                      (params->loopback_mode == LOOPBACK_EXT_PHY));
+
+       if (non_ext_phy ||
+           (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705)) {
+               if (params->req_line_speed == SPEED_AUTO_NEG)
+                       bnx2x_set_parallel_detection(params, vars->phy_flags);
+               bnx2x_init_internal_phy(params, vars);
        }
 
-       /* init ext phy and enable link state int */
-       rc |= bnx2x_ext_phy_init(params, vars);
+       if (!non_ext_phy)
+               rc |= bnx2x_ext_phy_init(params, vars);
 
        bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
-                      (NIG_STATUS_XGXS0_LINK10G |
-                       NIG_STATUS_XGXS0_LINK_STATUS |
-                       NIG_STATUS_SERDES0_LINK_STATUS));
+                    (NIG_STATUS_XGXS0_LINK10G |
+                     NIG_STATUS_XGXS0_LINK_STATUS |
+                     NIG_STATUS_SERDES0_LINK_STATUS));
 
        return rc;
 
@@ -3730,15 +3917,23 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
        struct bnx2x *bp = params->bp;
 
        u32 val;
-       DP(NETIF_MSG_LINK, "Phy Initialization started\n");
+       DP(NETIF_MSG_LINK, "Phy Initialization started \n");
        DP(NETIF_MSG_LINK, "req_speed = %d, req_flowctrl=%d\n",
                  params->req_line_speed, params->req_flow_ctrl);
        vars->link_status = 0;
+       vars->phy_link_up = 0;
+       vars->link_up = 0;
+       vars->line_speed = 0;
+       vars->duplex = DUPLEX_FULL;
+       vars->flow_ctrl = FLOW_CTRL_NONE;
+       vars->mac_type = MAC_TYPE_NONE;
+
        if (params->switch_cfg ==  SWITCH_CFG_1G)
                vars->phy_flags = PHY_SERDES_FLAG;
        else
                vars->phy_flags = PHY_XGXS_FLAG;
 
+
        /* disable attentions */
        bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
                       (NIG_MASK_XGXS0_LINK_STATUS |
@@ -3894,6 +4089,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
                }
 
                bnx2x_link_initialize(params, vars);
+               msleep(30);
                bnx2x_link_int_enable(params);
        }
        return 0;
@@ -3943,39 +4139,22 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars)
                        /* HW reset */
 
                        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-                                      MISC_REGISTERS_GPIO_OUTPUT_LOW);
+                                         MISC_REGISTERS_GPIO_OUTPUT_LOW,
+                                         port);
 
                        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                      MISC_REGISTERS_GPIO_OUTPUT_LOW);
+                                         MISC_REGISTERS_GPIO_OUTPUT_LOW,
+                                         port);
 
                        DP(NETIF_MSG_LINK, "reset external PHY\n");
-               } else {
-
-                       u8 ext_phy_addr = ((ext_phy_config &
-                                        PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
-                                        PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
-
-                       /* SW reset */
-                       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-                                      MDIO_PMA_DEVAD,
-                                      MDIO_PMA_REG_CTRL,
-                                      1<<15);
-
-                       /* Set Low Power Mode */
-                       bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-                                 MDIO_PMA_DEVAD,
-                                 MDIO_PMA_REG_CTRL,
-                                 1<<11);
-
-
-                       if (ext_phy_type ==
-                           PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-                               DP(NETIF_MSG_LINK, "Setting 8073 port %d into"
+               } else if (ext_phy_type ==
+                          PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
+                               DP(NETIF_MSG_LINK, "Setting 8073 port %d into "
                                         "low power mode\n",
                                         port);
                                bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                       MISC_REGISTERS_GPIO_OUTPUT_LOW);
-                       }
+                                       MISC_REGISTERS_GPIO_OUTPUT_LOW,
+                                                 port);
                }
        }
        /* reset the SerDes/XGXS */
@@ -3995,6 +4174,73 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars)
        return 0;
 }
 
+static u8 bnx2x_update_link_down(struct link_params *params,
+                              struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       u8 port = params->port;
+       DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
+       bnx2x_set_led(bp, port, LED_MODE_OFF,
+                   0, params->hw_led_mode,
+                   params->chip_id);
+
+       /* indicate no mac active */
+       vars->mac_type = MAC_TYPE_NONE;
+
+       /* update shared memory */
+       vars->link_status = 0;
+       vars->line_speed = 0;
+       bnx2x_update_mng(params, vars->link_status);
+
+       /* activate nig drain */
+       REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
+
+       /* reset BigMac */
+       bnx2x_bmac_rx_disable(bp, params->port);
+       REG_WR(bp, GRCBASE_MISC +
+                  MISC_REGISTERS_RESET_REG_2_CLEAR,
+                  (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+       return 0;
+}
+
+static u8 bnx2x_update_link_up(struct link_params *params,
+                            struct link_vars *vars,
+                            u8 link_10g, u32 gp_status)
+{
+       struct bnx2x *bp = params->bp;
+       u8 port = params->port;
+       u8 rc = 0;
+       vars->link_status |= LINK_STATUS_LINK_UP;
+       if (link_10g) {
+               bnx2x_bmac_enable(params, vars, 0);
+               bnx2x_set_led(bp, port, LED_MODE_OPER,
+                           SPEED_10000, params->hw_led_mode,
+                           params->chip_id);
+
+       } else {
+               bnx2x_emac_enable(params, vars, 0);
+               rc = bnx2x_emac_program(params, vars->line_speed,
+                                     vars->duplex);
+
+               /* AN complete? */
+               if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
+                       if (!(vars->phy_flags &
+                             PHY_SGMII_FLAG))
+                               bnx2x_set_sgmii_tx_driver(params);
+               }
+       }
+
+       /* PBF - link up */
+       rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
+                             vars->line_speed);
+
+       /* disable drain */
+       REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
+
+       /* update shared memory */
+       bnx2x_update_mng(params, vars->link_status);
+       return rc;
+}
 /* This function should called upon link interrupt */
 /* In case vars->link_up, driver needs to
        1. Update the pbf
@@ -4012,10 +4258,10 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
        u8 port = params->port;
-       u16 i;
        u16 gp_status;
-       u16 link_10g;
-       u8 rc = 0;
+       u8 link_10g;
+       u8 ext_phy_link_up, rc = 0;
+       u32 ext_phy_type;
 
        DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
         port,
@@ -4031,15 +4277,16 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
          REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
          REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
 
+       ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
 
-       /* avoid fast toggling */
-       for (i = 0; i < 10; i++) {
-               msleep(10);
-               CL45_RD_OVER_CL22(bp, port, params->phy_addr,
-                                     MDIO_REG_BANK_GP_STATUS,
-                                     MDIO_GP_STATUS_TOP_AN_STATUS1,
-                                     &gp_status);
-       }
+       /* Check external link change only for non-direct */
+       ext_phy_link_up = bnx2x_ext_phy_is_link_up(params, vars);
+
+       /* Read gp_status */
+       CL45_RD_OVER_CL22(bp, port, params->phy_addr,
+                             MDIO_REG_BANK_GP_STATUS,
+                             MDIO_GP_STATUS_TOP_AN_STATUS1,
+                             &gp_status);
 
        rc = bnx2x_link_settings_status(params, vars, gp_status);
        if (rc != 0)
@@ -4055,73 +4302,177 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 
        bnx2x_link_int_ack(params, vars, link_10g);
 
+       /* In case external phy link is up, and internal link is down
+       ( not initialized yet probably after link initialization, it needs
+       to be initialized.
+       Note that after link down-up as result of cable plug,
+       the xgxs link would probably become up again without the need to
+       initialize it*/
+
+       if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
+           (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) &&
+           (ext_phy_link_up && !vars->phy_link_up))
+               bnx2x_init_internal_phy(params, vars);
+
        /* link is up only if both local phy and external phy are up */
-       vars->link_up = (vars->phy_link_up &&
-                          bnx2x_ext_phy_is_link_up(params, vars));
+       vars->link_up = (ext_phy_link_up && vars->phy_link_up);
 
-       if (!vars->phy_link_up &&
-           REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18)) {
-               bnx2x_ext_phy_is_link_up(params, vars); /* Clear interrupt */
+       if (vars->link_up)
+               rc = bnx2x_update_link_up(params, vars, link_10g, gp_status);
+       else
+               rc = bnx2x_update_link_down(params, vars);
+
+       return rc;
+}
+
+static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
+{
+       u8 ext_phy_addr[PORT_MAX];
+       u16 val;
+       s8 port;
+
+       /* PART1 - Reset both phys */
+       for (port = PORT_MAX - 1; port >= PORT_0; port--) {
+               /* Extract the ext phy address for the port */
+               u32 ext_phy_config = REG_RD(bp, shmem_base +
+                                       offsetof(struct shmem_region,
+                  dev_info.port_hw_config[port].external_phy_config));
+
+               /* disable attentions */
+               bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
+                            (NIG_MASK_XGXS0_LINK_STATUS |
+                             NIG_MASK_XGXS0_LINK10G |
+                             NIG_MASK_SERDES0_LINK_STATUS |
+                             NIG_MASK_MI_INT));
+
+               ext_phy_addr[port] =
+                       ((ext_phy_config &
+                             PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
+                             PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+
+               /* Need to take the phy out of low power mode in order
+                       to write to access its registers */
+               bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+                                 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
+
+               /* Reset the phy */
+               bnx2x_cl45_write(bp, port,
+                              PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                              ext_phy_addr[port],
+                              MDIO_PMA_DEVAD,
+                              MDIO_PMA_REG_CTRL,
+                              1<<15);
        }
 
-       if (vars->link_up) {
-               vars->link_status |= LINK_STATUS_LINK_UP;
-               if (link_10g) {
-                       bnx2x_bmac_enable(params, vars, 0);
-                       bnx2x_set_led(bp, port, LED_MODE_OPER,
-                                   SPEED_10000, params->hw_led_mode,
-                                   params->chip_id);
+       /* Add delay of 150ms after reset */
+       msleep(150);
 
-               } else {
-                       bnx2x_emac_enable(params, vars, 0);
-                       rc = bnx2x_emac_program(params, vars->line_speed,
-                                             vars->duplex);
+       /* PART2 - Download firmware to both phys */
+       for (port = PORT_MAX - 1; port >= PORT_0; port--) {
+               u16 fw_ver1;
 
-                       /* AN complete? */
-                       if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
-                               if (!(vars->phy_flags &
-                                     PHY_SGMII_FLAG))
-                                       bnx2x_set_sgmii_tx_driver(params);
-                       }
+               bnx2x_bcm8073_external_rom_boot(bp, port,
+                                                     ext_phy_addr[port]);
+
+               bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                             ext_phy_addr[port],
+                             MDIO_PMA_DEVAD,
+                             MDIO_PMA_REG_ROM_VER1, &fw_ver1);
+               if (fw_ver1 == 0) {
+                       DP(NETIF_MSG_LINK,
+                                "bnx2x_8073_common_init_phy port %x "
+                                "fw Download failed\n", port);
+                       return -EINVAL;
                }
 
-               /* PBF - link up */
-               rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
-                                     vars->line_speed);
+               /* Only set bit 10 = 1 (Tx power down) */
+               bnx2x_cl45_read(bp, port,
+                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                             ext_phy_addr[port],
+                             MDIO_PMA_DEVAD,
+                             MDIO_PMA_REG_TX_POWER_DOWN, &val);
 
-               /* disable drain */
-               REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
+               /* Phase1 of TX_POWER_DOWN reset */
+               bnx2x_cl45_write(bp, port,
+                              PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                              ext_phy_addr[port],
+                              MDIO_PMA_DEVAD,
+                              MDIO_PMA_REG_TX_POWER_DOWN,
+                              (val | 1<<10));
+       }
 
-               /* update shared memory */
-               bnx2x_update_mng(params, vars->link_status);
+       /* Toggle Transmitter: Power down and then up with 600ms
+          delay between */
+       msleep(600);
 
-       } else { /* link down */
-               DP(NETIF_MSG_LINK, "Port %x: Link is down\n", params->port);
-               bnx2x_set_led(bp, port, LED_MODE_OFF,
-                           0, params->hw_led_mode,
-                           params->chip_id);
+       /* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
+       for (port = PORT_MAX - 1; port >= PORT_0; port--) {
+               /* Phase2 of POWER_DOWN_RESET*/
+               /* Release bit 10 (Release Tx power down) */
+               bnx2x_cl45_read(bp, port,
+                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                             ext_phy_addr[port],
+                             MDIO_PMA_DEVAD,
+                             MDIO_PMA_REG_TX_POWER_DOWN, &val);
 
-               /* indicate no mac active */
-               vars->mac_type = MAC_TYPE_NONE;
+               bnx2x_cl45_write(bp, port,
+                              PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                              ext_phy_addr[port],
+                              MDIO_PMA_DEVAD,
+                              MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
+               msleep(15);
 
-               /* update shared memory */
-               vars->link_status = 0;
-               bnx2x_update_mng(params, vars->link_status);
+               /* Read modify write the SPI-ROM version select register */
+               bnx2x_cl45_read(bp, port,
+                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                             ext_phy_addr[port],
+                             MDIO_PMA_DEVAD,
+                             MDIO_PMA_REG_EDC_FFE_MAIN, &val);
+               bnx2x_cl45_write(bp, port,
+                             PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+                             ext_phy_addr[port],
+                             MDIO_PMA_DEVAD,
+                             MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
 
-               /* activate nig drain */
-               REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
+               /* set GPIO2 back to LOW */
+               bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+                                 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
+       }
+       return 0;
 
-               /* reset BigMac */
-               bnx2x_bmac_rx_disable(bp, params->port);
-               REG_WR(bp, GRCBASE_MISC +
-                          MISC_REGISTERS_RESET_REG_2_CLEAR,
-                          (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+}
+
+u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
+{
+       u8 rc = 0;
+       u32 ext_phy_type;
 
+       DP(NETIF_MSG_LINK, "bnx2x_common_init_phy\n");
+
+       /* Read the ext_phy_type for arbitrary port(0) */
+       ext_phy_type = XGXS_EXT_PHY_TYPE(
+                       REG_RD(bp, shmem_base +
+                          offsetof(struct shmem_region,
+                            dev_info.port_hw_config[0].external_phy_config)));
+
+       switch (ext_phy_type) {
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
+       {
+               rc = bnx2x_8073_common_init_phy(bp, shmem_base);
+               break;
+       }
+       default:
+               DP(NETIF_MSG_LINK,
+                        "bnx2x_common_init_phy: ext_phy 0x%x not required\n",
+                        ext_phy_type);
+               break;
        }
 
        return rc;
 }
 
+
+
 static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
 {
        u16 val, cnt;
@@ -4154,7 +4505,7 @@ static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
 }
 #define RESERVED_SIZE 256
 /* max application is 160K bytes - data at end of RAM */
-#define MAX_APP_SIZE 160*1024 - RESERVED_SIZE
+#define MAX_APP_SIZE (160*1024 - RESERVED_SIZE)
 
 /* Header is 14 bytes */
 #define HEADER_SIZE 14
@@ -4192,12 +4543,12 @@ static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port,
                size = MAX_APP_SIZE+HEADER_SIZE;
        }
        DP(NETIF_MSG_LINK, "File version is %c%c\n", data[0x14e], data[0x14f]);
-       DP(NETIF_MSG_LINK, "                %c%c\n", data[0x150], data[0x151]);
+       DP(NETIF_MSG_LINK, "          %c%c\n", data[0x150], data[0x151]);
        /* Put the DSP in download mode by setting FLASH_CFG[2] to 1
           and issuing a reset.*/
 
        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-                         MISC_REGISTERS_GPIO_HIGH);
+                         MISC_REGISTERS_GPIO_HIGH, port);
 
        bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
 
@@ -4429,7 +4780,8 @@ static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port,
        }
 
        /* DSP Remove Download Mode */
-       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, MISC_REGISTERS_GPIO_LOW);
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
+                         MISC_REGISTERS_GPIO_LOW, port);
 
        bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
 
@@ -4437,7 +4789,7 @@ static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port,
        for (cnt = 0; cnt < 100; cnt++)
                msleep(5);
 
-       bnx2x_hw_reset(bp);
+       bnx2x_hw_reset(bp, port);
 
        for (cnt = 0; cnt < 100; cnt++)
                msleep(5);
@@ -4473,7 +4825,7 @@ static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port,
                      MDIO_PMA_REG_7101_VER2,
                      &image_revision2);
 
-       if (data[0x14e] != (image_revision2&0xFF) ||
+       if (data[0x14e] != (image_revision2&0xFF) ||
            data[0x14f] != ((image_revision2&0xFF00)>>8) ||
            data[0x150] != (image_revision1&0xFF) ||
            data[0x151] != ((image_revision1&0xFF00)>>8)) {
@@ -4508,11 +4860,11 @@ u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config,
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
                /* Take ext phy out of reset */
                if (!driver_loaded)
-                       bnx2x_turn_on_sf(bp, port, ext_phy_addr);
+                       bnx2x_turn_on_ef(bp, port, ext_phy_addr, ext_phy_type);
                rc = bnx2x_sfx7101_flash_download(bp, port, ext_phy_addr,
                                                data, size);
                if (!driver_loaded)
-                       bnx2x_turn_off_sf(bp);
+                       bnx2x_turn_off_sf(bp, port);
                break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
index 714d37ac95ded41591eb3b7cc129d7e1967eb4d3..86d54a17b41127c7bcb278d7e3b971305c6a3b27 100644 (file)
@@ -55,14 +55,17 @@ struct link_params {
 #define LOOPBACK_BMAC  2
 #define LOOPBACK_XGXS_10       3
 #define LOOPBACK_EXT_PHY       4
+#define LOOPBACK_EXT   5
 
        u16 req_duplex;
        u16 req_flow_ctrl;
+       u16 req_fc_auto_adv; /* Should be set to TX / BOTH when
+       req_flow_ctrl is set to AUTO */
        u16 req_line_speed; /* Also determine AutoNeg */
 
        /* Device parameters */
        u8 mac_addr[6];
-       u16 mtu;
+
 
 
        /* shmem parameters */
@@ -140,7 +143,7 @@ u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
                  u8 phy_addr, u8 devad, u16 reg, u16 val);
 
 /* Reads the link_status from the shmem,
-   and update the link vars accordinaly */
+   and update the link vars accordingly */
 void bnx2x_link_status_update(struct link_params *input,
                            struct link_vars *output);
 /* returns string representing the fw_version of the external phy */
@@ -149,7 +152,7 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
 
 /* Set/Unset the led
    Basically, the CLC takes care of the led for the link, but in case one needs
-   to set/unset the led unnatually, set the "mode" to LED_MODE_OPER to
+   to set/unset the led unnaturally, set the "mode" to LED_MODE_OPER to
    blink the led, and LED_MODE_OFF to set the led off.*/
 u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
               u16 hw_led_mode, u32 chip_id);
@@ -164,5 +167,7 @@ u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config,
        otherwise link is down*/
 u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars);
 
+/* One-time initialization for external phy after power up */
+u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base);
 
 #endif /* BNX2X_LINK_H */
index 272a4bd25953e3d1e91007530a507d4599a4fb2b..3e7dc171cdf10858c94d87a4874cadcdfbb24246 100644 (file)
@@ -60,8 +60,8 @@
 #include "bnx2x.h"
 #include "bnx2x_init.h"
 
-#define DRV_MODULE_VERSION      "1.45.6"
-#define DRV_MODULE_RELDATE      "2008/06/23"
+#define DRV_MODULE_VERSION      "1.45.17"
+#define DRV_MODULE_RELDATE      "2008/08/13"
 #define BNX2X_BC_VER           0x040200
 
 /* Time in jiffies before concluding the transmitter is hung */
@@ -76,23 +76,21 @@ MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
+static int disable_tpa;
 static int use_inta;
 static int poll;
 static int debug;
-static int disable_tpa;
-static int nomcp;
 static int load_count[3]; /* 0-common, 1-port0, 2-port1 */
 static int use_multi;
 
+module_param(disable_tpa, int, 0);
 module_param(use_inta, int, 0);
 module_param(poll, int, 0);
 module_param(debug, int, 0);
-module_param(disable_tpa, int, 0);
-module_param(nomcp, int, 0);
+MODULE_PARM_DESC(disable_tpa, "disable the TPA (LRO) feature");
 MODULE_PARM_DESC(use_inta, "use INT#A instead of MSI-X");
 MODULE_PARM_DESC(poll, "use polling (for debug)");
 MODULE_PARM_DESC(debug, "default debug msglevel");
-MODULE_PARM_DESC(nomcp, "ignore management CPU");
 
 #ifdef BNX2X_MULTI
 module_param(use_multi, int, 0);
@@ -237,17 +235,16 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
        while (*wb_comp != DMAE_COMP_VAL) {
                DP(BNX2X_MSG_OFF, "wb_comp 0x%08x\n", *wb_comp);
 
-               /* adjust delay for emulation/FPGA */
-               if (CHIP_REV_IS_SLOW(bp))
-                       msleep(100);
-               else
-                       udelay(5);
-
                if (!cnt) {
                        BNX2X_ERR("dmae timeout!\n");
                        break;
                }
                cnt--;
+               /* adjust delay for emulation/FPGA */
+               if (CHIP_REV_IS_SLOW(bp))
+                       msleep(100);
+               else
+                       udelay(5);
        }
 
        mutex_unlock(&bp->dmae_mutex);
@@ -310,17 +307,16 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
 
        while (*wb_comp != DMAE_COMP_VAL) {
 
-               /* adjust delay for emulation/FPGA */
-               if (CHIP_REV_IS_SLOW(bp))
-                       msleep(100);
-               else
-                       udelay(5);
-
                if (!cnt) {
                        BNX2X_ERR("dmae timeout!\n");
                        break;
                }
                cnt--;
+               /* adjust delay for emulation/FPGA */
+               if (CHIP_REV_IS_SLOW(bp))
+                       msleep(100);
+               else
+                       udelay(5);
        }
        DP(BNX2X_MSG_OFF, "data [0x%08x 0x%08x 0x%08x 0x%08x]\n",
           bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
@@ -503,6 +499,9 @@ static void bnx2x_panic_dump(struct bnx2x *bp)
        int i;
        u16 j, start, end;
 
+       bp->stats_state = STATS_STATE_DISABLED;
+       DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
+
        BNX2X_ERR("begin crash dump -----------------\n");
 
        for_each_queue(bp, i) {
@@ -513,17 +512,20 @@ static void bnx2x_panic_dump(struct bnx2x *bp)
                          "  tx_bd_prod(%x)  tx_bd_cons(%x)  *tx_cons_sb(%x)\n",
                          i, fp->tx_pkt_prod, fp->tx_pkt_cons, fp->tx_bd_prod,
                          fp->tx_bd_cons, le16_to_cpu(*fp->tx_cons_sb));
-               BNX2X_ERR("          rx_comp_prod(%x)  rx_comp_cons(%x)"
-                         "  *rx_cons_sb(%x)  *rx_bd_cons_sb(%x)"
-                         "  rx_sge_prod(%x)  last_max_sge(%x)\n",
-                         fp->rx_comp_prod, fp->rx_comp_cons,
-                         le16_to_cpu(*fp->rx_cons_sb),
-                         le16_to_cpu(*fp->rx_bd_cons_sb),
-                         fp->rx_sge_prod, fp->last_max_sge);
-               BNX2X_ERR("          fp_c_idx(%x)  fp_u_idx(%x)"
-                         "  bd data(%x,%x)  rx_alloc_failed(%lx)\n",
-                         fp->fp_c_idx, fp->fp_u_idx, hw_prods->packets_prod,
-                         hw_prods->bds_prod, fp->rx_alloc_failed);
+               BNX2X_ERR("          rx_bd_prod(%x)  rx_bd_cons(%x)"
+                         "  *rx_bd_cons_sb(%x)  rx_comp_prod(%x)"
+                         "  rx_comp_cons(%x)  *rx_cons_sb(%x)\n",
+                         fp->rx_bd_prod, fp->rx_bd_cons,
+                         le16_to_cpu(*fp->rx_bd_cons_sb), fp->rx_comp_prod,
+                         fp->rx_comp_cons, le16_to_cpu(*fp->rx_cons_sb));
+               BNX2X_ERR("          rx_sge_prod(%x)  last_max_sge(%x)"
+                         "  fp_c_idx(%x)  *sb_c_idx(%x)  fp_u_idx(%x)"
+                         "  *sb_u_idx(%x)  bd data(%x,%x)\n",
+                         fp->rx_sge_prod, fp->last_max_sge, fp->fp_c_idx,
+                         fp->status_blk->c_status_block.status_block_index,
+                         fp->fp_u_idx,
+                         fp->status_blk->u_status_block.status_block_index,
+                         hw_prods->packets_prod, hw_prods->bds_prod);
 
                start = TX_BD(le16_to_cpu(*fp->tx_cons_sb) - 10);
                end = TX_BD(le16_to_cpu(*fp->tx_cons_sb) + 245);
@@ -553,8 +555,8 @@ static void bnx2x_panic_dump(struct bnx2x *bp)
                                  j, rx_bd[1], rx_bd[0], sw_bd->skb);
                }
 
-               start = 0;
-               end = RX_SGE_CNT*NUM_RX_SGE_PAGES;
+               start = RX_SGE(fp->rx_sge_prod);
+               end = RX_SGE(fp->last_max_sge);
                for (j = start; j < end; j++) {
                        u32 *rx_sge = (u32 *)&fp->rx_sge_ring[j];
                        struct sw_rx_page *sw_page = &fp->rx_page_ring[j];
@@ -582,9 +584,6 @@ static void bnx2x_panic_dump(struct bnx2x *bp)
        bnx2x_fw_dump(bp);
        bnx2x_mc_assert(bp);
        BNX2X_ERR("end crash dump -----------------\n");
-
-       bp->stats_state = STATS_STATE_DISABLED;
-       DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
 }
 
 static void bnx2x_int_enable(struct bnx2x *bp)
@@ -684,7 +683,8 @@ static void bnx2x_int_disable_sync(struct bnx2x *bp)
 static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
                                u8 storm, u16 index, u8 op, u8 update)
 {
-       u32 igu_addr = (IGU_ADDR_INT_ACK + IGU_FUNC_BASE * BP_FUNC(bp)) * 8;
+       u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
+                      COMMAND_REG_INT_ACK);
        struct igu_ack_register igu_ack;
 
        igu_ack.status_block_index = index;
@@ -694,9 +694,9 @@ static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
                         (update << IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT) |
                         (op << IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT));
 
-       DP(BNX2X_MSG_OFF, "write 0x%08x to IGU addr 0x%x\n",
-          (*(u32 *)&igu_ack), BAR_IGU_INTMEM + igu_addr);
-       REG_WR(bp, BAR_IGU_INTMEM + igu_addr, (*(u32 *)&igu_ack));
+       DP(BNX2X_MSG_OFF, "write 0x%08x to HC addr 0x%x\n",
+          (*(u32 *)&igu_ack), hc_addr);
+       REG_WR(bp, hc_addr, (*(u32 *)&igu_ack));
 }
 
 static inline u16 bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
@@ -716,36 +716,15 @@ static inline u16 bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
        return rc;
 }
 
-static inline int bnx2x_has_work(struct bnx2x_fastpath *fp)
-{
-       u16 rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
-
-       if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
-               rx_cons_sb++;
-
-       if ((fp->rx_comp_cons != rx_cons_sb) ||
-           (fp->tx_pkt_prod != le16_to_cpu(*fp->tx_cons_sb)) ||
-           (fp->tx_pkt_prod != fp->tx_pkt_cons))
-               return 1;
-
-       return 0;
-}
-
 static u16 bnx2x_ack_int(struct bnx2x *bp)
 {
-       u32 igu_addr = (IGU_ADDR_SIMD_MASK + IGU_FUNC_BASE * BP_FUNC(bp)) * 8;
-       u32 result = REG_RD(bp, BAR_IGU_INTMEM + igu_addr);
+       u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
+                      COMMAND_REG_SIMD_MASK);
+       u32 result = REG_RD(bp, hc_addr);
 
-       DP(BNX2X_MSG_OFF, "read 0x%08x from IGU addr 0x%x\n",
-          result, BAR_IGU_INTMEM + igu_addr);
+       DP(BNX2X_MSG_OFF, "read 0x%08x from HC addr 0x%x\n",
+          result, hc_addr);
 
-#ifdef IGU_DEBUG
-#warning IGU_DEBUG active
-       if (result == 0) {
-               BNX2X_ERR("read %x from IGU\n", result);
-               REG_WR(bp, TM_REG_TIMER_SOFT_RST, 0);
-       }
-#endif
        return result;
 }
 
@@ -898,6 +877,7 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp, int work)
                netif_tx_lock(bp->dev);
 
                if (netif_queue_stopped(bp->dev) &&
+                   (bp->state == BNX2X_STATE_OPEN) &&
                    (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3))
                        netif_wake_queue(bp->dev);
 
@@ -905,6 +885,7 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp, int work)
        }
 }
 
+
 static void bnx2x_sp_event(struct bnx2x_fastpath *fp,
                           union eth_rx_cqe *rr_cqe)
 {
@@ -960,6 +941,7 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp,
                bnx2x_fp(bp, cid, state) = BNX2X_FP_STATE_CLOSED;
                break;
 
+
        case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_OPEN):
        case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_DIAG):
                DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
@@ -1169,8 +1151,8 @@ static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp)
        memset(fp->sge_mask, 0xff,
               (NUM_RX_SGE >> RX_SGE_MASK_ELEM_SHIFT)*sizeof(u64));
 
-       /* Clear the two last indeces in the page to 1:
-          these are the indeces that correspond to the "next" element,
+       /* Clear the two last indices in the page to 1:
+          these are the indices that correspond to the "next" element,
           hence will never be indicated and should be removed from
           the calculations. */
        bnx2x_clear_sge_mask_next_elems(fp);
@@ -1261,7 +1243,7 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                   where we are and drop the whole packet */
                err = bnx2x_alloc_rx_sge(bp, fp, sge_idx);
                if (unlikely(err)) {
-                       fp->rx_alloc_failed++;
+                       bp->eth_stats.rx_skb_alloc_failed++;
                        return err;
                }
 
@@ -1297,14 +1279,13 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        pci_unmap_single(bp->pdev, pci_unmap_addr(rx_buf, mapping),
                         bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
 
-       /* if alloc failed drop the packet and keep the buffer in the bin */
        if (likely(new_skb)) {
+               /* fix ip xsum and give it to the stack */
+               /* (no need to map the new skb) */
 
                prefetch(skb);
                prefetch(((char *)(skb)) + 128);
 
-               /* else fix ip xsum and give it to the stack */
-               /* (no need to map the new skb) */
 #ifdef BNX2X_STOP_ON_ERROR
                if (pad + len > bp->rx_buf_size) {
                        BNX2X_ERR("skb_put is about to fail...  "
@@ -1353,9 +1334,10 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                fp->tpa_pool[queue].skb = new_skb;
 
        } else {
+               /* else drop the packet and keep the buffer in the bin */
                DP(NETIF_MSG_RX_STATUS,
                   "Failed to allocate new skb - dropping packet!\n");
-               fp->rx_alloc_failed++;
+               bp->eth_stats.rx_skb_alloc_failed++;
        }
 
        fp->tpa_state[queue] = BNX2X_TPA_STOP;
@@ -1390,7 +1372,6 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
        u16 bd_cons, bd_prod, bd_prod_fw, comp_ring_cons;
        u16 hw_comp_cons, sw_comp_cons, sw_comp_prod;
        int rx_pkt = 0;
-       u16 queue;
 
 #ifdef BNX2X_STOP_ON_ERROR
        if (unlikely(bp->panic))
@@ -1456,7 +1437,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                        if ((!fp->disable_tpa) &&
                            (TPA_TYPE(cqe_fp_flags) !=
                                        (TPA_TYPE_START | TPA_TYPE_END))) {
-                               queue = cqe->fast_path_cqe.queue_index;
+                               u16 queue = cqe->fast_path_cqe.queue_index;
 
                                if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_START) {
                                        DP(NETIF_MSG_RX_STATUS,
@@ -1503,11 +1484,10 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 
                        /* is this an error packet? */
                        if (unlikely(cqe_fp_flags & ETH_RX_ERROR_FALGS)) {
-                       /* do we sometimes forward error packets anyway? */
                                DP(NETIF_MSG_RX_ERR,
                                   "ERROR  flags %x  rx packet %u\n",
                                   cqe_fp_flags, sw_comp_cons);
-                               /* TBD make sure MC counts this as a drop */
+                               bp->eth_stats.rx_err_discard_pkt++;
                                goto reuse_rx;
                        }
 
@@ -1524,7 +1504,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                                        DP(NETIF_MSG_RX_ERR,
                                           "ERROR  packet dropped "
                                           "because of alloc failure\n");
-                                       fp->rx_alloc_failed++;
+                                       bp->eth_stats.rx_skb_alloc_failed++;
                                        goto reuse_rx;
                                }
 
@@ -1550,7 +1530,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                                DP(NETIF_MSG_RX_ERR,
                                   "ERROR  packet dropped because "
                                   "of alloc failure\n");
-                               fp->rx_alloc_failed++;
+                               bp->eth_stats.rx_skb_alloc_failed++;
 reuse_rx:
                                bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod);
                                goto next_rx;
@@ -1559,10 +1539,12 @@ reuse_rx:
                        skb->protocol = eth_type_trans(skb, bp->dev);
 
                        skb->ip_summed = CHECKSUM_NONE;
-                       if (bp->rx_csum && BNX2X_RX_SUM_OK(cqe))
-                               skb->ip_summed = CHECKSUM_UNNECESSARY;
-
-                       /* TBD do we pass bad csum packets in promisc */
+                       if (bp->rx_csum) {
+                               if (likely(BNX2X_RX_CSUM_OK(cqe)))
+                                       skb->ip_summed = CHECKSUM_UNNECESSARY;
+                               else
+                                       bp->eth_stats.hw_csum_err++;
+                       }
                }
 
 #ifdef BCM_VLAN
@@ -1615,6 +1597,12 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
        struct net_device *dev = bp->dev;
        int index = FP_IDX(fp);
 
+       /* Return here if interrupt is disabled */
+       if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
+               DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
+               return IRQ_HANDLED;
+       }
+
        DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB [%d:%d]\n",
           index, FP_SB_ID(fp));
        bnx2x_ack_sb(bp, FP_SB_ID(fp), USTORM_ID, 0, IGU_INT_DISABLE, 0);
@@ -1648,17 +1636,17 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
        }
        DP(NETIF_MSG_INTR, "got an interrupt  status %u\n", status);
 
-#ifdef BNX2X_STOP_ON_ERROR
-       if (unlikely(bp->panic))
-               return IRQ_HANDLED;
-#endif
-
        /* Return here if interrupt is disabled */
        if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
                DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
                return IRQ_HANDLED;
        }
 
+#ifdef BNX2X_STOP_ON_ERROR
+       if (unlikely(bp->panic))
+               return IRQ_HANDLED;
+#endif
+
        mask = 0x2 << bp->fp[0].sb_id;
        if (status & mask) {
                struct bnx2x_fastpath *fp = &bp->fp[0];
@@ -1699,11 +1687,12 @@ static void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
  * General service functions
  */
 
-static int bnx2x_hw_lock(struct bnx2x *bp, u32 resource)
+static int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource)
 {
        u32 lock_status;
        u32 resource_bit = (1 << resource);
-       u8 port = BP_PORT(bp);
+       int func = BP_FUNC(bp);
+       u32 hw_lock_control_reg;
        int cnt;
 
        /* Validating that the resource is within range */
@@ -1714,8 +1703,15 @@ static int bnx2x_hw_lock(struct bnx2x *bp, u32 resource)
                return -EINVAL;
        }
 
+       if (func <= 5) {
+               hw_lock_control_reg = (MISC_REG_DRIVER_CONTROL_1 + func*8);
+       } else {
+               hw_lock_control_reg =
+                               (MISC_REG_DRIVER_CONTROL_7 + (func - 6)*8);
+       }
+
        /* Validating that the resource is not already taken */
-       lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + port*8);
+       lock_status = REG_RD(bp, hw_lock_control_reg);
        if (lock_status & resource_bit) {
                DP(NETIF_MSG_HW, "lock_status 0x%x  resource_bit 0x%x\n",
                   lock_status, resource_bit);
@@ -1725,9 +1721,8 @@ static int bnx2x_hw_lock(struct bnx2x *bp, u32 resource)
        /* Try for 1 second every 5ms */
        for (cnt = 0; cnt < 200; cnt++) {
                /* Try to acquire the lock */
-               REG_WR(bp, MISC_REG_DRIVER_CONTROL_1 + port*8 + 4,
-                      resource_bit);
-               lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + port*8);
+               REG_WR(bp, hw_lock_control_reg + 4, resource_bit);
+               lock_status = REG_RD(bp, hw_lock_control_reg);
                if (lock_status & resource_bit)
                        return 0;
 
@@ -1737,11 +1732,12 @@ static int bnx2x_hw_lock(struct bnx2x *bp, u32 resource)
        return -EAGAIN;
 }
 
-static int bnx2x_hw_unlock(struct bnx2x *bp, u32 resource)
+static int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource)
 {
        u32 lock_status;
        u32 resource_bit = (1 << resource);
-       u8 port = BP_PORT(bp);
+       int func = BP_FUNC(bp);
+       u32 hw_lock_control_reg;
 
        /* Validating that the resource is within range */
        if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
@@ -1751,20 +1747,27 @@ static int bnx2x_hw_unlock(struct bnx2x *bp, u32 resource)
                return -EINVAL;
        }
 
+       if (func <= 5) {
+               hw_lock_control_reg = (MISC_REG_DRIVER_CONTROL_1 + func*8);
+       } else {
+               hw_lock_control_reg =
+                               (MISC_REG_DRIVER_CONTROL_7 + (func - 6)*8);
+       }
+
        /* Validating that the resource is currently taken */
-       lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + port*8);
+       lock_status = REG_RD(bp, hw_lock_control_reg);
        if (!(lock_status & resource_bit)) {
                DP(NETIF_MSG_HW, "lock_status 0x%x  resource_bit 0x%x\n",
                   lock_status, resource_bit);
                return -EFAULT;
        }
 
-       REG_WR(bp, MISC_REG_DRIVER_CONTROL_1 + port*8, resource_bit);
+       REG_WR(bp, hw_lock_control_reg, resource_bit);
        return 0;
 }
 
 /* HW Lock for shared dual port PHYs */
-static void bnx2x_phy_hw_lock(struct bnx2x *bp)
+static void bnx2x_acquire_phy_lock(struct bnx2x *bp)
 {
        u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
 
@@ -1772,25 +1775,25 @@ static void bnx2x_phy_hw_lock(struct bnx2x *bp)
 
        if ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) ||
            (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073))
-               bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO);
+               bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO);
 }
 
-static void bnx2x_phy_hw_unlock(struct bnx2x *bp)
+static void bnx2x_release_phy_lock(struct bnx2x *bp)
 {
        u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
 
        if ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) ||
            (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073))
-               bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO);
+               bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO);
 
        mutex_unlock(&bp->port.phy_mutex);
 }
 
-int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode)
+int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port)
 {
        /* The GPIO should be swapped if swap register is set and active */
        int gpio_port = (REG_RD(bp, NIG_REG_PORT_SWAP) &&
-                        REG_RD(bp, NIG_REG_STRAP_OVERRIDE)) ^ BP_PORT(bp);
+                        REG_RD(bp, NIG_REG_STRAP_OVERRIDE)) ^ port;
        int gpio_shift = gpio_num +
                        (gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0);
        u32 gpio_mask = (1 << gpio_shift);
@@ -1801,7 +1804,7 @@ int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode)
                return -EINVAL;
        }
 
-       bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
+       bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
        /* read GPIO and mask except the float bits */
        gpio_reg = (REG_RD(bp, MISC_REG_GPIO) & MISC_REGISTERS_GPIO_FLOAT);
 
@@ -1822,7 +1825,7 @@ int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode)
                gpio_reg |=  (gpio_mask << MISC_REGISTERS_GPIO_SET_POS);
                break;
 
-       case MISC_REGISTERS_GPIO_INPUT_HI_Z :
+       case MISC_REGISTERS_GPIO_INPUT_HI_Z:
                DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> input\n",
                   gpio_num, gpio_shift);
                /* set FLOAT */
@@ -1834,7 +1837,7 @@ int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode)
        }
 
        REG_WR(bp, MISC_REG_GPIO, gpio_reg);
-       bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_GPIO);
+       bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
 
        return 0;
 }
@@ -1850,19 +1853,19 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
                return -EINVAL;
        }
 
-       bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_SPIO);
+       bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_SPIO);
        /* read SPIO and mask except the float bits */
        spio_reg = (REG_RD(bp, MISC_REG_SPIO) & MISC_REGISTERS_SPIO_FLOAT);
 
        switch (mode) {
-       case MISC_REGISTERS_SPIO_OUTPUT_LOW :
+       case MISC_REGISTERS_SPIO_OUTPUT_LOW:
                DP(NETIF_MSG_LINK, "Set SPIO %d -> output low\n", spio_num);
                /* clear FLOAT and set CLR */
                spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
                spio_reg |=  (spio_mask << MISC_REGISTERS_SPIO_CLR_POS);
                break;
 
-       case MISC_REGISTERS_SPIO_OUTPUT_HIGH :
+       case MISC_REGISTERS_SPIO_OUTPUT_HIGH:
                DP(NETIF_MSG_LINK, "Set SPIO %d -> output high\n", spio_num);
                /* clear FLOAT and set SET */
                spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
@@ -1880,7 +1883,7 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
        }
 
        REG_WR(bp, MISC_REG_SPIO, spio_reg);
-       bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_SPIO);
+       bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_SPIO);
 
        return 0;
 }
@@ -1940,46 +1943,63 @@ static void bnx2x_link_report(struct bnx2x *bp)
 
 static u8 bnx2x_initial_phy_init(struct bnx2x *bp)
 {
-       u8 rc;
+       if (!BP_NOMCP(bp)) {
+               u8 rc;
 
-       /* Initialize link parameters structure variables */
-       bp->link_params.mtu = bp->dev->mtu;
+               /* Initialize link parameters structure variables */
+               /* It is recommended to turn off RX FC for jumbo frames
+                  for better performance */
+               if (IS_E1HMF(bp))
+                       bp->link_params.req_fc_auto_adv = FLOW_CTRL_BOTH;
+               else if (bp->dev->mtu > 5000)
+                       bp->link_params.req_fc_auto_adv = FLOW_CTRL_TX;
+               else
+                       bp->link_params.req_fc_auto_adv = FLOW_CTRL_BOTH;
 
-       bnx2x_phy_hw_lock(bp);
-       rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
-       bnx2x_phy_hw_unlock(bp);
+               bnx2x_acquire_phy_lock(bp);
+               rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
+               bnx2x_release_phy_lock(bp);
 
-       if (bp->link_vars.link_up)
-               bnx2x_link_report(bp);
+               if (bp->link_vars.link_up)
+                       bnx2x_link_report(bp);
 
-       bnx2x_calc_fc_adv(bp);
+               bnx2x_calc_fc_adv(bp);
 
-       return rc;
+               return rc;
+       }
+       BNX2X_ERR("Bootcode is missing -not initializing link\n");
+       return -EINVAL;
 }
 
 static void bnx2x_link_set(struct bnx2x *bp)
 {
-       bnx2x_phy_hw_lock(bp);
-       bnx2x_phy_init(&bp->link_params, &bp->link_vars);
-       bnx2x_phy_hw_unlock(bp);
+       if (!BP_NOMCP(bp)) {
+               bnx2x_acquire_phy_lock(bp);
+               bnx2x_phy_init(&bp->link_params, &bp->link_vars);
+               bnx2x_release_phy_lock(bp);
 
-       bnx2x_calc_fc_adv(bp);
+               bnx2x_calc_fc_adv(bp);
+       } else
+               BNX2X_ERR("Bootcode is missing -not setting link\n");
 }
 
 static void bnx2x__link_reset(struct bnx2x *bp)
 {
-       bnx2x_phy_hw_lock(bp);
-       bnx2x_link_reset(&bp->link_params, &bp->link_vars);
-       bnx2x_phy_hw_unlock(bp);
+       if (!BP_NOMCP(bp)) {
+               bnx2x_acquire_phy_lock(bp);
+               bnx2x_link_reset(&bp->link_params, &bp->link_vars);
+               bnx2x_release_phy_lock(bp);
+       } else
+               BNX2X_ERR("Bootcode is missing -not resetting link\n");
 }
 
 static u8 bnx2x_link_test(struct bnx2x *bp)
 {
        u8 rc;
 
-       bnx2x_phy_hw_lock(bp);
+       bnx2x_acquire_phy_lock(bp);
        rc = bnx2x_test_link(&bp->link_params, &bp->link_vars);
-       bnx2x_phy_hw_unlock(bp);
+       bnx2x_release_phy_lock(bp);
 
        return rc;
 }
@@ -1991,7 +2011,7 @@ static u8 bnx2x_link_test(struct bnx2x *bp)
      sum of vn_min_rates
        or
      0 - if all the min_rates are 0.
-     In the later case fainess algorithm should be deactivated.
+     In the later case fairness algorithm should be deactivated.
      If not all min_rates are zero then those that are zeroes will
      be set to 1.
  */
@@ -2114,7 +2134,7 @@ static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func,
                                FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
                /* If FAIRNESS is enabled (not all min rates are zeroes) and
                   if current min rate is zero - set it to 1.
-                  This is a requirment of the algorithm. */
+                  This is a requirement of the algorithm. */
                if ((vn_min_rate == 0) && wsum)
                        vn_min_rate = DEF_MIN_RATE;
                vn_max_rate = ((vn_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
@@ -2203,9 +2223,9 @@ static void bnx2x_link_attn(struct bnx2x *bp)
        /* Make sure that we are synced with the current statistics */
        bnx2x_stats_handle(bp, STATS_EVENT_STOP);
 
-       bnx2x_phy_hw_lock(bp);
+       bnx2x_acquire_phy_lock(bp);
        bnx2x_link_update(&bp->link_params, &bp->link_vars);
-       bnx2x_phy_hw_unlock(bp);
+       bnx2x_release_phy_lock(bp);
 
        if (bp->link_vars.link_up) {
 
@@ -2357,7 +2377,7 @@ static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 }
 
 /* acquire split MCP access lock register */
-static int bnx2x_lock_alr(struct bnx2x *bp)
+static int bnx2x_acquire_alr(struct bnx2x *bp)
 {
        u32 i, j, val;
        int rc = 0;
@@ -2374,15 +2394,15 @@ static int bnx2x_lock_alr(struct bnx2x *bp)
                msleep(5);
        }
        if (!(val & (1L << 31))) {
-               BNX2X_ERR("Cannot acquire nvram interface\n");
+               BNX2X_ERR("Cannot acquire MCP access lock register\n");
                rc = -EBUSY;
        }
 
        return rc;
 }
 
-/* Release split MCP access lock register */
-static void bnx2x_unlock_alr(struct bnx2x *bp)
+/* release split MCP access lock register */
+static void bnx2x_release_alr(struct bnx2x *bp)
 {
        u32 val = 0;
 
@@ -2395,7 +2415,6 @@ static inline u16 bnx2x_update_dsb_idx(struct bnx2x *bp)
        u16 rc = 0;
 
        barrier(); /* status block is written to by the chip */
-
        if (bp->def_att_idx != def_sb->atten_status_block.attn_bits_index) {
                bp->def_att_idx = def_sb->atten_status_block.attn_bits_index;
                rc |= 1;
@@ -2426,26 +2445,31 @@ static inline u16 bnx2x_update_dsb_idx(struct bnx2x *bp)
 static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
 {
        int port = BP_PORT(bp);
-       int func = BP_FUNC(bp);
-       u32 igu_addr = (IGU_ADDR_ATTN_BITS_SET + IGU_FUNC_BASE * func) * 8;
+       u32 hc_addr = (HC_REG_COMMAND_REG + port*32 +
+                      COMMAND_REG_ATTN_BITS_SET);
        u32 aeu_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
                              MISC_REG_AEU_MASK_ATTN_FUNC_0;
        u32 nig_int_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 :
                                       NIG_REG_MASK_INTERRUPT_PORT0;
+       u32 aeu_mask;
 
-       if (~bp->aeu_mask & (asserted & 0xff))
-               BNX2X_ERR("IGU ERROR\n");
        if (bp->attn_state & asserted)
                BNX2X_ERR("IGU ERROR\n");
 
+       bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port);
+       aeu_mask = REG_RD(bp, aeu_addr);
+
        DP(NETIF_MSG_HW, "aeu_mask %x  newly asserted %x\n",
-          bp->aeu_mask, asserted);
-       bp->aeu_mask &= ~(asserted & 0xff);
-       DP(NETIF_MSG_HW, "after masking: aeu_mask %x\n", bp->aeu_mask);
+          aeu_mask, asserted);
+       aeu_mask &= ~(asserted & 0xff);
+       DP(NETIF_MSG_HW, "new mask %x\n", aeu_mask);
 
-       REG_WR(bp, aeu_addr, bp->aeu_mask);
+       REG_WR(bp, aeu_addr, aeu_mask);
+       bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port);
 
+       DP(NETIF_MSG_HW, "attn_state %x\n", bp->attn_state);
        bp->attn_state |= asserted;
+       DP(NETIF_MSG_HW, "new state %x\n", bp->attn_state);
 
        if (asserted & ATTN_HARD_WIRED_MASK) {
                if (asserted & ATTN_NIG_FOR_FUNC) {
@@ -2500,9 +2524,9 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
 
        } /* if hardwired */
 
-       DP(NETIF_MSG_HW, "about to mask 0x%08x at IGU addr 0x%x\n",
-          asserted, BAR_IGU_INTMEM + igu_addr);
-       REG_WR(bp, BAR_IGU_INTMEM + igu_addr, asserted);
+       DP(NETIF_MSG_HW, "about to mask 0x%08x at HC addr 0x%x\n",
+          asserted, hc_addr);
+       REG_WR(bp, hc_addr, asserted);
 
        /* now set back the mask */
        if (asserted & ATTN_NIG_FOR_FUNC)
@@ -2530,12 +2554,12 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
                case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
                        /* Fan failure attention */
 
-                       /* The PHY reset is controled by GPIO 1 */
+                       /* The PHY reset is controlled by GPIO 1 */
                        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-                                      MISC_REGISTERS_GPIO_OUTPUT_LOW);
-                       /* Low power mode is controled by GPIO 2 */
+                                      MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
+                       /* Low power mode is controlled by GPIO 2 */
                        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                      MISC_REGISTERS_GPIO_OUTPUT_LOW);
+                                      MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
                        /* mark the failure */
                        bp->link_params.ext_phy_config &=
                                        ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
@@ -2699,10 +2723,11 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
        int index;
        u32 reg_addr;
        u32 val;
+       u32 aeu_mask;
 
        /* need to take HW lock because MCP or other port might also
           try to handle this event */
-       bnx2x_lock_alr(bp);
+       bnx2x_acquire_alr(bp);
 
        attn.sig[0] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_1_FUNC_0 + port*4);
        attn.sig[1] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 + port*4);
@@ -2734,32 +2759,35 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
                                                HW_PRTY_ASSERT_SET_1) ||
                            (attn.sig[2] & group_mask.sig[2] &
                                                HW_PRTY_ASSERT_SET_2))
-                              BNX2X_ERR("FATAL HW block parity attention\n");
+                               BNX2X_ERR("FATAL HW block parity attention\n");
                }
        }
 
-       bnx2x_unlock_alr(bp);
+       bnx2x_release_alr(bp);
 
-       reg_addr = (IGU_ADDR_ATTN_BITS_CLR + IGU_FUNC_BASE * BP_FUNC(bp)) * 8;
+       reg_addr = (HC_REG_COMMAND_REG + port*32 + COMMAND_REG_ATTN_BITS_CLR);
 
        val = ~deasserted;
-/*     DP(NETIF_MSG_INTR, "write 0x%08x to IGU addr 0x%x\n",
-          val, BAR_IGU_INTMEM + reg_addr); */
-       REG_WR(bp, BAR_IGU_INTMEM + reg_addr, val);
+       DP(NETIF_MSG_HW, "about to mask 0x%08x at HC addr 0x%x\n",
+          val, reg_addr);
+       REG_WR(bp, reg_addr, val);
 
-       if (bp->aeu_mask & (deasserted & 0xff))
-               BNX2X_ERR("IGU BUG!\n");
        if (~bp->attn_state & deasserted)
-               BNX2X_ERR("IGU BUG!\n");
+               BNX2X_ERR("IGU ERROR\n");
 
        reg_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
                          MISC_REG_AEU_MASK_ATTN_FUNC_0;
 
-       DP(NETIF_MSG_HW, "aeu_mask %x\n", bp->aeu_mask);
-       bp->aeu_mask |= (deasserted & 0xff);
+       bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port);
+       aeu_mask = REG_RD(bp, reg_addr);
+
+       DP(NETIF_MSG_HW, "aeu_mask %x  newly deasserted %x\n",
+          aeu_mask, deasserted);
+       aeu_mask |= (deasserted & 0xff);
+       DP(NETIF_MSG_HW, "new mask %x\n", aeu_mask);
 
-       DP(NETIF_MSG_HW, "new mask %x\n", bp->aeu_mask);
-       REG_WR(bp, reg_addr, bp->aeu_mask);
+       REG_WR(bp, reg_addr, aeu_mask);
+       bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port);
 
        DP(NETIF_MSG_HW, "attn_state %x\n", bp->attn_state);
        bp->attn_state &= ~deasserted;
@@ -2800,7 +2828,7 @@ static void bnx2x_sp_task(struct work_struct *work)
 
        /* Return here if interrupt is disabled */
        if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
-               DP(BNX2X_MSG_SP, "called but intr_sem not 0, returning\n");
+               DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
                return;
        }
 
@@ -2808,7 +2836,7 @@ static void bnx2x_sp_task(struct work_struct *work)
 /*     if (status == 0)                                     */
 /*             BNX2X_ERR("spurious slowpath interrupt!\n"); */
 
-       DP(BNX2X_MSG_SP, "got a slowpath interrupt (updated %x)\n", status);
+       DP(NETIF_MSG_INTR, "got a slowpath interrupt (updated %x)\n", status);
 
        /* HW attentions */
        if (status & 0x1)
@@ -2838,7 +2866,7 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
 
        /* Return here if interrupt is disabled */
        if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
-               DP(BNX2X_MSG_SP, "called but intr_sem not 0, returning\n");
+               DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
                return IRQ_HANDLED;
        }
 
@@ -2876,11 +2904,11 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
                        /* underflow */ \
                        d_hi = m_hi - s_hi; \
                        if (d_hi > 0) { \
-                       /* we can 'loan' 1 */ \
+                               /* we can 'loan' 1 */ \
                                d_hi--; \
                                d_lo = m_lo + (UINT_MAX - s_lo) + 1; \
                        } else { \
-                       /* m_hi <= s_hi */ \
+                               /* m_hi <= s_hi */ \
                                d_hi = 0; \
                                d_lo = 0; \
                        } \
@@ -2890,7 +2918,7 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
                                d_hi = 0; \
                                d_lo = 0; \
                        } else { \
-                       /* m_hi >= s_hi */ \
+                               /* m_hi >= s_hi */ \
                                d_hi = m_hi - s_hi; \
                                d_lo = m_lo - s_lo; \
                        } \
@@ -2963,37 +2991,6 @@ static inline long bnx2x_hilo(u32 *hiref)
  * Init service functions
  */
 
-static void bnx2x_storm_stats_init(struct bnx2x *bp)
-{
-       int func = BP_FUNC(bp);
-
-       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(func), 1);
-       REG_WR(bp, BAR_XSTRORM_INTMEM +
-              XSTORM_STATS_FLAGS_OFFSET(func) + 4, 0);
-
-       REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(func), 1);
-       REG_WR(bp, BAR_TSTRORM_INTMEM +
-              TSTORM_STATS_FLAGS_OFFSET(func) + 4, 0);
-
-       REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(func), 0);
-       REG_WR(bp, BAR_CSTRORM_INTMEM +
-              CSTORM_STATS_FLAGS_OFFSET(func) + 4, 0);
-
-       REG_WR(bp, BAR_XSTRORM_INTMEM +
-              XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func),
-              U64_LO(bnx2x_sp_mapping(bp, fw_stats)));
-       REG_WR(bp, BAR_XSTRORM_INTMEM +
-              XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func) + 4,
-              U64_HI(bnx2x_sp_mapping(bp, fw_stats)));
-
-       REG_WR(bp, BAR_TSTRORM_INTMEM +
-              TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func),
-              U64_LO(bnx2x_sp_mapping(bp, fw_stats)));
-       REG_WR(bp, BAR_TSTRORM_INTMEM +
-              TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func) + 4,
-              U64_HI(bnx2x_sp_mapping(bp, fw_stats)));
-}
-
 static void bnx2x_storm_stats_post(struct bnx2x *bp)
 {
        if (!bp->stats_pending) {
@@ -3032,6 +3029,8 @@ static void bnx2x_stats_init(struct bnx2x *bp)
        memset(&(bp->port.old_nig_stats), 0, sizeof(struct nig_stats));
        bp->port.old_nig_stats.brb_discard =
                        REG_RD(bp, NIG_REG_STAT0_BRB_DISCARD + port*0x38);
+       bp->port.old_nig_stats.brb_truncate =
+                       REG_RD(bp, NIG_REG_STAT0_BRB_TRUNCATE + port*0x38);
        REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50,
                    &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2);
        REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50,
@@ -3101,12 +3100,12 @@ static int bnx2x_stats_comp(struct bnx2x *bp)
 
        might_sleep();
        while (*stats_comp != DMAE_COMP_VAL) {
-               msleep(1);
                if (!cnt) {
                        BNX2X_ERR("timeout waiting for stats finished\n");
                        break;
                }
                cnt--;
+               msleep(1);
        }
        return 1;
 }
@@ -3451,8 +3450,7 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp)
        UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong);
        UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments);
        UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
-       UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
-       UPDATE_STAT64(rx_stat_grxcf, rx_stat_bmac_xcf);
+       UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
        UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
        UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffpauseframesreceived);
        UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
@@ -3536,6 +3534,8 @@ static int bnx2x_hw_stats_update(struct bnx2x *bp)
 
        ADD_EXTEND_64(pstats->brb_drop_hi, pstats->brb_drop_lo,
                      new->brb_discard - old->brb_discard);
+       ADD_EXTEND_64(estats->brb_truncate_hi, estats->brb_truncate_lo,
+                     new->brb_truncate - old->brb_truncate);
 
        UPDATE_STAT64_NIG(egress_mac_pkt0,
                                        etherstatspkts1024octetsto1522octets);
@@ -3713,8 +3713,7 @@ static void bnx2x_net_stats_update(struct bnx2x *bp)
        nstats->rx_length_errors =
                                estats->rx_stat_etherstatsundersizepkts_lo +
                                estats->jabber_packets_received;
-       nstats->rx_over_errors = estats->brb_drop_lo +
-                                estats->brb_truncate_discard;
+       nstats->rx_over_errors = estats->brb_drop_lo + estats->brb_truncate_lo;
        nstats->rx_crc_errors = estats->rx_stat_dot3statsfcserrors_lo;
        nstats->rx_frame_errors = estats->rx_stat_dot3statsalignmenterrors_lo;
        nstats->rx_fifo_errors = old_tclient->no_buff_discard;
@@ -3783,7 +3782,7 @@ static void bnx2x_stats_update(struct bnx2x *bp)
                             bp->fp->rx_comp_cons),
                       le16_to_cpu(*bp->fp->rx_cons_sb), nstats->rx_packets);
                printk(KERN_DEBUG "  %s (Xoff events %u)  brb drops %u\n",
-                      netif_queue_stopped(bp->dev)? "Xoff" : "Xon",
+                      netif_queue_stopped(bp->dev) ? "Xoff" : "Xon",
                       estats->driver_xoff, estats->brb_drop_lo);
                printk(KERN_DEBUG "tstats: checksum_discard %u  "
                        "packets_too_big_discard %u  no_buff_discard %u  "
@@ -3994,14 +3993,14 @@ static void bnx2x_zero_sb(struct bnx2x *bp, int sb_id)
 
        bnx2x_init_fill(bp, BAR_USTRORM_INTMEM +
                        USTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0,
-                       sizeof(struct ustorm_def_status_block)/4);
+                       sizeof(struct ustorm_status_block)/4);
        bnx2x_init_fill(bp, BAR_CSTRORM_INTMEM +
                        CSTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0,
-                       sizeof(struct cstorm_def_status_block)/4);
+                       sizeof(struct cstorm_status_block)/4);
 }
 
-static void bnx2x_init_sb(struct bnx2x *bp, int sb_id,
-                         struct host_status_block *sb, dma_addr_t mapping)
+static void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb,
+                         dma_addr_t mapping, int sb_id)
 {
        int port = BP_PORT(bp);
        int func = BP_FUNC(bp);
@@ -4077,7 +4076,6 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                                            atten_status_block);
        def_sb->atten_status_block.status_block_id = sb_id;
 
-       bp->def_att_idx = 0;
        bp->attn_state = 0;
 
        reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
@@ -4094,9 +4092,6 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                                               reg_offset + 0xc + 0x10*index);
        }
 
-       bp->aeu_mask = REG_RD(bp, (port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
-                                         MISC_REG_AEU_MASK_ATTN_FUNC_0));
-
        reg_offset = (port ? HC_REG_ATTN_MSG1_ADDR_L :
                             HC_REG_ATTN_MSG0_ADDR_L);
 
@@ -4114,17 +4109,13 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                                            u_def_status_block);
        def_sb->u_def_status_block.status_block_id = sb_id;
 
-       bp->def_u_idx = 0;
-
        REG_WR(bp, BAR_USTRORM_INTMEM +
               USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
        REG_WR(bp, BAR_USTRORM_INTMEM +
               ((USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
               U64_HI(section));
-       REG_WR8(bp, BAR_USTRORM_INTMEM +  DEF_USB_FUNC_OFF +
+       REG_WR8(bp, BAR_USTRORM_INTMEM + DEF_USB_FUNC_OFF +
                USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
-       REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_HC_BTR_OFFSET(func),
-              BNX2X_BTR);
 
        for (index = 0; index < HC_USTORM_DEF_SB_NUM_INDICES; index++)
                REG_WR16(bp, BAR_USTRORM_INTMEM +
@@ -4135,17 +4126,13 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                                            c_def_status_block);
        def_sb->c_def_status_block.status_block_id = sb_id;
 
-       bp->def_c_idx = 0;
-
        REG_WR(bp, BAR_CSTRORM_INTMEM +
               CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
        REG_WR(bp, BAR_CSTRORM_INTMEM +
               ((CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
               U64_HI(section));
-       REG_WR8(bp, BAR_CSTRORM_INTMEM +  DEF_CSB_FUNC_OFF +
+       REG_WR8(bp, BAR_CSTRORM_INTMEM + DEF_CSB_FUNC_OFF +
                CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
-       REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_OFFSET(func),
-              BNX2X_BTR);
 
        for (index = 0; index < HC_CSTORM_DEF_SB_NUM_INDICES; index++)
                REG_WR16(bp, BAR_CSTRORM_INTMEM +
@@ -4156,17 +4143,13 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                                            t_def_status_block);
        def_sb->t_def_status_block.status_block_id = sb_id;
 
-       bp->def_t_idx = 0;
-
        REG_WR(bp, BAR_TSTRORM_INTMEM +
               TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
        REG_WR(bp, BAR_TSTRORM_INTMEM +
               ((TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
               U64_HI(section));
-       REG_WR8(bp, BAR_TSTRORM_INTMEM +  DEF_TSB_FUNC_OFF +
+       REG_WR8(bp, BAR_TSTRORM_INTMEM + DEF_TSB_FUNC_OFF +
                TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
-       REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_HC_BTR_OFFSET(func),
-              BNX2X_BTR);
 
        for (index = 0; index < HC_TSTORM_DEF_SB_NUM_INDICES; index++)
                REG_WR16(bp, BAR_TSTRORM_INTMEM +
@@ -4177,23 +4160,20 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
                                            x_def_status_block);
        def_sb->x_def_status_block.status_block_id = sb_id;
 
-       bp->def_x_idx = 0;
-
        REG_WR(bp, BAR_XSTRORM_INTMEM +
               XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
        REG_WR(bp, BAR_XSTRORM_INTMEM +
               ((XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
               U64_HI(section));
-       REG_WR8(bp, BAR_XSTRORM_INTMEM +  DEF_XSB_FUNC_OFF +
+       REG_WR8(bp, BAR_XSTRORM_INTMEM + DEF_XSB_FUNC_OFF +
                XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
-       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_HC_BTR_OFFSET(func),
-              BNX2X_BTR);
 
        for (index = 0; index < HC_XSTORM_DEF_SB_NUM_INDICES; index++)
                REG_WR16(bp, BAR_XSTRORM_INTMEM +
                         XSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
 
        bp->stats_pending = 0;
+       bp->set_mac_pending = 0;
 
        bnx2x_ack_sb(bp, sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
 }
@@ -4209,21 +4189,25 @@ static void bnx2x_update_coalesce(struct bnx2x *bp)
                /* HC_INDEX_U_ETH_RX_CQ_CONS */
                REG_WR8(bp, BAR_USTRORM_INTMEM +
                        USTORM_SB_HC_TIMEOUT_OFFSET(port, sb_id,
-                                                  HC_INDEX_U_ETH_RX_CQ_CONS),
+                                                   U_SB_ETH_RX_CQ_INDEX),
                        bp->rx_ticks/12);
                REG_WR16(bp, BAR_USTRORM_INTMEM +
                         USTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
-                                                  HC_INDEX_U_ETH_RX_CQ_CONS),
+                                                    U_SB_ETH_RX_CQ_INDEX),
+                        bp->rx_ticks ? 0 : 1);
+               REG_WR16(bp, BAR_USTRORM_INTMEM +
+                        USTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
+                                                    U_SB_ETH_RX_BD_INDEX),
                         bp->rx_ticks ? 0 : 1);
 
                /* HC_INDEX_C_ETH_TX_CQ_CONS */
                REG_WR8(bp, BAR_CSTRORM_INTMEM +
                        CSTORM_SB_HC_TIMEOUT_OFFSET(port, sb_id,
-                                                  HC_INDEX_C_ETH_TX_CQ_CONS),
+                                                   C_SB_ETH_TX_CQ_INDEX),
                        bp->tx_ticks/12);
                REG_WR16(bp, BAR_CSTRORM_INTMEM +
                         CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
-                                                  HC_INDEX_C_ETH_TX_CQ_CONS),
+                                                    C_SB_ETH_TX_CQ_INDEX),
                         bp->tx_ticks ? 0 : 1);
        }
 }
@@ -4256,7 +4240,9 @@ static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
 static void bnx2x_init_rx_rings(struct bnx2x *bp)
 {
        int func = BP_FUNC(bp);
-       u16 ring_prod, cqe_ring_prod = 0;
+       int max_agg_queues = CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 :
+                                             ETH_MAX_AGGREGATION_QUEUES_E1H;
+       u16 ring_prod, cqe_ring_prod;
        int i, j;
 
        bp->rx_buf_use_size = bp->dev->mtu;
@@ -4270,9 +4256,9 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
                   bp->dev->mtu + ETH_OVREHEAD);
 
                for_each_queue(bp, j) {
-                       for (i = 0; i < ETH_MAX_AGGREGATION_QUEUES_E1H; i++) {
-                               struct bnx2x_fastpath *fp = &bp->fp[j];
+                       struct bnx2x_fastpath *fp = &bp->fp[j];
 
+                       for (i = 0; i < max_agg_queues; i++) {
                                fp->tpa_pool[i].skb =
                                   netdev_alloc_skb(bp->dev, bp->rx_buf_size);
                                if (!fp->tpa_pool[i].skb) {
@@ -4352,8 +4338,7 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
                                BNX2X_ERR("disabling TPA for queue[%d]\n", j);
                                /* Cleanup already allocated elements */
                                bnx2x_free_rx_sge_range(bp, fp, ring_prod);
-                               bnx2x_free_tpa_pool(bp, fp,
-                                             ETH_MAX_AGGREGATION_QUEUES_E1H);
+                               bnx2x_free_tpa_pool(bp, fp, max_agg_queues);
                                fp->disable_tpa = 1;
                                ring_prod = 0;
                                break;
@@ -4363,13 +4348,13 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
                fp->rx_sge_prod = ring_prod;
 
                /* Allocate BDs and initialize BD ring */
-               fp->rx_comp_cons = fp->rx_alloc_failed = 0;
+               fp->rx_comp_cons = 0;
                cqe_ring_prod = ring_prod = 0;
                for (i = 0; i < bp->rx_ring_size; i++) {
                        if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) {
                                BNX2X_ERR("was only able to allocate "
                                          "%d rx skbs\n", i);
-                               fp->rx_alloc_failed++;
+                               bp->eth_stats.rx_skb_alloc_failed++;
                                break;
                        }
                        ring_prod = NEXT_RX_IDX(ring_prod);
@@ -4497,7 +4482,7 @@ static void bnx2x_init_context(struct bnx2x *bp)
                }
 
                context->cstorm_st_context.sb_index_number =
-                                               HC_INDEX_C_ETH_TX_CQ_CONS;
+                                               C_SB_ETH_TX_CQ_INDEX;
                context->cstorm_st_context.status_block_id = sb_id;
 
                context->xstorm_ag_context.cdu_reserved =
@@ -4535,7 +4520,7 @@ static void bnx2x_set_client_config(struct bnx2x *bp)
        int i;
 
        tstorm_client.mtu = bp->dev->mtu + ETH_OVREHEAD;
-       tstorm_client.statistics_counter_id = 0;
+       tstorm_client.statistics_counter_id = BP_CL_ID(bp);
        tstorm_client.config_flags =
                                TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
 #ifdef BCM_VLAN
@@ -4579,7 +4564,7 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
        int func = BP_FUNC(bp);
        int i;
 
-       DP(NETIF_MSG_RX_STATUS, "rx mode is %d\n", mode);
+       DP(NETIF_MSG_IFUP, "rx mode %d  mask 0x%x\n", mode, mask);
 
        switch (mode) {
        case BNX2X_RX_MODE_NONE: /* no Rx */
@@ -4617,13 +4602,35 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
                bnx2x_set_client_config(bp);
 }
 
-static void bnx2x_init_internal(struct bnx2x *bp)
+static void bnx2x_init_internal_common(struct bnx2x *bp)
+{
+       int i;
+
+       /* Zero this manually as its initialization is
+          currently missing in the initTool */
+       for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
+               REG_WR(bp, BAR_USTRORM_INTMEM +
+                      USTORM_AGG_DATA_OFFSET + i * 4, 0);
+}
+
+static void bnx2x_init_internal_port(struct bnx2x *bp)
+{
+       int port = BP_PORT(bp);
+
+       REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
+       REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
+       REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
+       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
+}
+
+static void bnx2x_init_internal_func(struct bnx2x *bp)
 {
        struct tstorm_eth_function_common_config tstorm_config = {0};
        struct stats_indication_flags stats_flags = {0};
        int port = BP_PORT(bp);
        int func = BP_FUNC(bp);
        int i;
+       u16 max_agg_size;
 
        if (is_multi(bp)) {
                tstorm_config.config_flags = MULTI_FLAGS;
@@ -4636,31 +4643,53 @@ static void bnx2x_init_internal(struct bnx2x *bp)
               TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(func),
               (*(u32 *)&tstorm_config));
 
-/*     DP(NETIF_MSG_IFUP, "tstorm_config: 0x%08x\n",
-          (*(u32 *)&tstorm_config)); */
-
        bp->rx_mode = BNX2X_RX_MODE_NONE; /* no rx until link is up */
        bnx2x_set_storm_rx_mode(bp);
 
+       /* reset xstorm per client statistics */
+       for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++) {
+               REG_WR(bp, BAR_XSTRORM_INTMEM +
+                      XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, BP_CL_ID(bp)) +
+                      i*4, 0);
+       }
+       /* reset tstorm per client statistics */
+       for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++) {
+               REG_WR(bp, BAR_TSTRORM_INTMEM +
+                      TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, BP_CL_ID(bp)) +
+                      i*4, 0);
+       }
+
+       /* Init statistics related context */
        stats_flags.collect_eth = 1;
 
-       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(port),
+       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(func),
               ((u32 *)&stats_flags)[0]);
-       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(port) + 4,
+       REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(func) + 4,
               ((u32 *)&stats_flags)[1]);
 
-       REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(port),
+       REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(func),
               ((u32 *)&stats_flags)[0]);
-       REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(port) + 4,
+       REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(func) + 4,
               ((u32 *)&stats_flags)[1]);
 
-       REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(port),
+       REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(func),
               ((u32 *)&stats_flags)[0]);
-       REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(port) + 4,
+       REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(func) + 4,
               ((u32 *)&stats_flags)[1]);
 
-/*     DP(NETIF_MSG_IFUP, "stats_flags: 0x%08x 0x%08x\n",
-          ((u32 *)&stats_flags)[0], ((u32 *)&stats_flags)[1]); */
+       REG_WR(bp, BAR_XSTRORM_INTMEM +
+              XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func),
+              U64_LO(bnx2x_sp_mapping(bp, fw_stats)));
+       REG_WR(bp, BAR_XSTRORM_INTMEM +
+              XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func) + 4,
+              U64_HI(bnx2x_sp_mapping(bp, fw_stats)));
+
+       REG_WR(bp, BAR_TSTRORM_INTMEM +
+              TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func),
+              U64_LO(bnx2x_sp_mapping(bp, fw_stats)));
+       REG_WR(bp, BAR_TSTRORM_INTMEM +
+              TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func) + 4,
+              U64_HI(bnx2x_sp_mapping(bp, fw_stats)));
 
        if (CHIP_IS_E1H(bp)) {
                REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNCTION_MODE_OFFSET,
@@ -4676,15 +4705,12 @@ static void bnx2x_init_internal(struct bnx2x *bp)
                         bp->e1hov);
        }
 
-       /* Zero this manualy as its initialization is
-          currently missing in the initTool */
-       for (i = 0; i < USTORM_AGG_DATA_SIZE >> 2; i++)
-               REG_WR(bp, BAR_USTRORM_INTMEM +
-                      USTORM_AGG_DATA_OFFSET + 4*i, 0);
-
+       /* Init CQ ring mapping and aggregation size */
+       max_agg_size = min((u32)(bp->rx_buf_use_size +
+                                8*BCM_PAGE_SIZE*PAGES_PER_SGE),
+                          (u32)0xffff);
        for_each_queue(bp, i) {
                struct bnx2x_fastpath *fp = &bp->fp[i];
-               u16 max_agg_size;
 
                REG_WR(bp, BAR_USTRORM_INTMEM +
                       USTORM_CQE_PAGE_BASE_OFFSET(port, FP_CL_ID(fp)),
@@ -4693,16 +4719,34 @@ static void bnx2x_init_internal(struct bnx2x *bp)
                       USTORM_CQE_PAGE_BASE_OFFSET(port, FP_CL_ID(fp)) + 4,
                       U64_HI(fp->rx_comp_mapping));
 
-               max_agg_size = min((u32)(bp->rx_buf_use_size +
-                                        8*BCM_PAGE_SIZE*PAGES_PER_SGE),
-                                  (u32)0xffff);
                REG_WR16(bp, BAR_USTRORM_INTMEM +
                         USTORM_MAX_AGG_SIZE_OFFSET(port, FP_CL_ID(fp)),
                         max_agg_size);
        }
 }
 
-static void bnx2x_nic_init(struct bnx2x *bp)
+static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
+{
+       switch (load_code) {
+       case FW_MSG_CODE_DRV_LOAD_COMMON:
+               bnx2x_init_internal_common(bp);
+               /* no break */
+
+       case FW_MSG_CODE_DRV_LOAD_PORT:
+               bnx2x_init_internal_port(bp);
+               /* no break */
+
+       case FW_MSG_CODE_DRV_LOAD_FUNCTION:
+               bnx2x_init_internal_func(bp);
+               break;
+
+       default:
+               BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
+               break;
+       }
+}
+
+static void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
 {
        int i;
 
@@ -4717,19 +4761,20 @@ static void bnx2x_nic_init(struct bnx2x *bp)
                DP(NETIF_MSG_IFUP,
                   "bnx2x_init_sb(%p,%p) index %d  cl_id %d  sb %d\n",
                   bp, fp->status_blk, i, FP_CL_ID(fp), FP_SB_ID(fp));
-               bnx2x_init_sb(bp, FP_SB_ID(fp), fp->status_blk,
-                             fp->status_blk_mapping);
+               bnx2x_init_sb(bp, fp->status_blk, fp->status_blk_mapping,
+                             FP_SB_ID(fp));
+               bnx2x_update_fpsb_idx(fp);
        }
 
-       bnx2x_init_def_sb(bp, bp->def_status_blk,
-                         bp->def_status_blk_mapping, DEF_SB_ID);
+       bnx2x_init_def_sb(bp, bp->def_status_blk, bp->def_status_blk_mapping,
+                         DEF_SB_ID);
+       bnx2x_update_dsb_idx(bp);
        bnx2x_update_coalesce(bp);
        bnx2x_init_rx_rings(bp);
        bnx2x_init_tx_ring(bp);
        bnx2x_init_sp_ring(bp);
        bnx2x_init_context(bp);
-       bnx2x_init_internal(bp);
-       bnx2x_storm_stats_init(bp);
+       bnx2x_init_internal(bp, load_code);
        bnx2x_init_ind_table(bp);
        bnx2x_int_enable(bp);
 }
@@ -4878,7 +4923,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
        REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x0);
        REG_WR(bp, TCM_REG_PRS_IFEN, 0x0);
        REG_WR(bp, CFC_REG_DEBUG0, 0x1);
-       NIG_WR(NIG_REG_PRS_REQ_IN_EN, 0x0);
+       REG_WR(bp, NIG_REG_PRS_REQ_IN_EN, 0x0);
 
        /*  Write 0 to parser credits for CFC search request */
        REG_WR(bp, PRS_REG_CFC_SEARCH_INITIAL_CREDIT, 0x0);
@@ -4933,7 +4978,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
        REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x0);
        REG_WR(bp, TCM_REG_PRS_IFEN, 0x0);
        REG_WR(bp, CFC_REG_DEBUG0, 0x1);
-       NIG_WR(NIG_REG_PRS_REQ_IN_EN, 0x0);
+       REG_WR(bp, NIG_REG_PRS_REQ_IN_EN, 0x0);
 
        /* Write 0 to parser credits for CFC search request */
        REG_WR(bp, PRS_REG_CFC_SEARCH_INITIAL_CREDIT, 0x0);
@@ -5000,7 +5045,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
        REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x7fffffff);
        REG_WR(bp, TCM_REG_PRS_IFEN, 0x1);
        REG_WR(bp, CFC_REG_DEBUG0, 0x0);
-       NIG_WR(NIG_REG_PRS_REQ_IN_EN, 0x1);
+       REG_WR(bp, NIG_REG_PRS_REQ_IN_EN, 0x1);
 
        DP(NETIF_MSG_HW, "done\n");
 
@@ -5089,11 +5134,6 @@ static int bnx2x_init_common(struct bnx2x *bp)
        REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
 #endif
 
-#ifndef BCM_ISCSI
-               /* set NIC mode */
-               REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif
-
        REG_WR(bp, PXP2_REG_RQ_CDU_P_SIZE, 2);
 #ifdef BCM_ISCSI
        REG_WR(bp, PXP2_REG_RQ_TM_P_SIZE, 5);
@@ -5163,6 +5203,8 @@ static int bnx2x_init_common(struct bnx2x *bp)
        }
 
        bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
+       /* set NIC mode */
+       REG_WR(bp, PRS_REG_NIC_MODE, 1);
        if (CHIP_IS_E1H(bp))
                REG_WR(bp, PRS_REG_E1HOV_MODE, IS_E1HMF(bp));
 
@@ -5333,6 +5375,13 @@ static int bnx2x_init_common(struct bnx2x *bp)
                       ((u32 *)&tmp)[1]);
        }
 
+       if (!BP_NOMCP(bp)) {
+               bnx2x_acquire_phy_lock(bp);
+               bnx2x_common_init_phy(bp, bp->common.shmem_base);
+               bnx2x_release_phy_lock(bp);
+       } else
+               BNX2X_ERR("Bootcode is missing - can not initialize link\n");
+
        return 0;
 }
 
@@ -5638,18 +5687,23 @@ static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
        int func = BP_FUNC(bp);
        u32 seq = ++bp->fw_seq;
        u32 rc = 0;
+       u32 cnt = 1;
+       u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10;
 
        SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq));
        DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
 
-       /* let the FW do it's magic ... */
-       msleep(100); /* TBD */
+       do {
+               /* let the FW do it's magic ... */
+               msleep(delay);
 
-       if (CHIP_REV_IS_SLOW(bp))
-               msleep(900);
+               rc = SHMEM_RD(bp, func_mb[func].fw_mb_header);
 
-       rc = SHMEM_RD(bp, func_mb[func].fw_mb_header);
-       DP(BNX2X_MSG_MCP, "read (%x) seq is (%x) from FW MB\n", rc, seq);
+               /* Give the FW up to 2 second (200*10ms) */
+       } while ((seq != (rc & FW_MSG_SEQ_NUMBER_MASK)) && (cnt++ < 200));
+
+       DP(BNX2X_MSG_MCP, "[after %d ms] read (%x) seq is (%x) from FW MB\n",
+          cnt*delay, rc, seq);
 
        /* is this a reply to our command? */
        if (seq == (rc & FW_MSG_SEQ_NUMBER_MASK)) {
@@ -5713,6 +5767,7 @@ static void bnx2x_free_mem(struct bnx2x *bp)
                               NUM_RCQ_BD);
 
                /* SGE ring */
+               BNX2X_FREE(bnx2x_fp(bp, i, rx_page_ring));
                BNX2X_PCI_FREE(bnx2x_fp(bp, i, rx_sge_ring),
                               bnx2x_fp(bp, i, rx_sge_mapping),
                               BCM_PAGE_SIZE * NUM_RX_SGE_PAGES);
@@ -5890,7 +5945,8 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
                        dev_kfree_skb(skb);
                }
                if (!fp->disable_tpa)
-                       bnx2x_free_tpa_pool(bp, fp,
+                       bnx2x_free_tpa_pool(bp, fp, CHIP_IS_E1(bp) ?
+                                           ETH_MAX_AGGREGATION_QUEUES_E1 :
                                            ETH_MAX_AGGREGATION_QUEUES_E1H);
        }
 }
@@ -5976,8 +6032,8 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
                                 bnx2x_msix_fp_int, 0,
                                 bp->dev->name, &bp->fp[i]);
                if (rc) {
-                       BNX2X_ERR("request fp #%d irq failed  rc %d\n",
-                                 i + offset, rc);
+                       BNX2X_ERR("request fp #%d irq failed  rc -%d\n",
+                                 i + offset, -rc);
                        bnx2x_free_msix_irqs(bp);
                        return -EBUSY;
                }
@@ -6004,7 +6060,7 @@ static int bnx2x_req_irq(struct bnx2x *bp)
  * Init service functions
  */
 
-static void bnx2x_set_mac_addr_e1(struct bnx2x *bp)
+static void bnx2x_set_mac_addr_e1(struct bnx2x *bp, int set)
 {
        struct mac_configuration_cmd *config = bnx2x_sp(bp, mac_config);
        int port = BP_PORT(bp);
@@ -6026,11 +6082,15 @@ static void bnx2x_set_mac_addr_e1(struct bnx2x *bp)
        config->config_table[0].cam_entry.lsb_mac_addr =
                                        swab16(*(u16 *)&bp->dev->dev_addr[4]);
        config->config_table[0].cam_entry.flags = cpu_to_le16(port);
-       config->config_table[0].target_table_entry.flags = 0;
+       if (set)
+               config->config_table[0].target_table_entry.flags = 0;
+       else
+               CAM_INVALIDATE(config->config_table[0]);
        config->config_table[0].target_table_entry.client_id = 0;
        config->config_table[0].target_table_entry.vlan_id = 0;
 
-       DP(NETIF_MSG_IFUP, "setting MAC (%04x:%04x:%04x)\n",
+       DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x)\n",
+          (set ? "setting" : "clearing"),
           config->config_table[0].cam_entry.msb_mac_addr,
           config->config_table[0].cam_entry.middle_mac_addr,
           config->config_table[0].cam_entry.lsb_mac_addr);
@@ -6040,8 +6100,11 @@ static void bnx2x_set_mac_addr_e1(struct bnx2x *bp)
        config->config_table[1].cam_entry.middle_mac_addr = 0xffff;
        config->config_table[1].cam_entry.lsb_mac_addr = 0xffff;
        config->config_table[1].cam_entry.flags = cpu_to_le16(port);
-       config->config_table[1].target_table_entry.flags =
+       if (set)
+               config->config_table[1].target_table_entry.flags =
                                TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST;
+       else
+               CAM_INVALIDATE(config->config_table[1]);
        config->config_table[1].target_table_entry.client_id = 0;
        config->config_table[1].target_table_entry.vlan_id = 0;
 
@@ -6050,12 +6113,12 @@ static void bnx2x_set_mac_addr_e1(struct bnx2x *bp)
                      U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0);
 }
 
-static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp)
+static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp, int set)
 {
        struct mac_configuration_cmd_e1h *config =
                (struct mac_configuration_cmd_e1h *)bnx2x_sp(bp, mac_config);
 
-       if (bp->state != BNX2X_STATE_OPEN) {
+       if (set && (bp->state != BNX2X_STATE_OPEN)) {
                DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
                return;
        }
@@ -6079,9 +6142,14 @@ static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp)
        config->config_table[0].client_id = BP_L_ID(bp);
        config->config_table[0].vlan_id = 0;
        config->config_table[0].e1hov_id = cpu_to_le16(bp->e1hov);
-       config->config_table[0].flags = BP_PORT(bp);
+       if (set)
+               config->config_table[0].flags = BP_PORT(bp);
+       else
+               config->config_table[0].flags =
+                               MAC_CONFIGURATION_ENTRY_E1H_ACTION_TYPE;
 
-       DP(NETIF_MSG_IFUP, "setting MAC (%04x:%04x:%04x)  E1HOV %d  CLID %d\n",
+       DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x)  E1HOV %d  CLID %d\n",
+          (set ? "setting" : "clearing"),
           config->config_table[0].msb_mac_addr,
           config->config_table[0].middle_mac_addr,
           config->config_table[0].lsb_mac_addr, bp->e1hov, BP_L_ID(bp));
@@ -6106,13 +6174,13 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
                        bnx2x_rx_int(bp->fp, 10);
                        /* if index is different from 0
                         * the reply for some commands will
-                        * be on the none default queue
+                        * be on the non default queue
                         */
                        if (idx)
                                bnx2x_rx_int(&bp->fp[idx], 10);
                }
-               mb(); /* state is changed by bnx2x_sp_event() */
 
+               mb(); /* state is changed by bnx2x_sp_event() */
                if (*state_p == state)
                        return 0;
 
@@ -6167,7 +6235,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 {
        u32 load_code;
        int i, rc;
-
 #ifdef BNX2X_STOP_ON_ERROR
        if (unlikely(bp->panic))
                return -EPERM;
@@ -6183,22 +6250,24 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
        if (!BP_NOMCP(bp)) {
                load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ);
                if (!load_code) {
-                       BNX2X_ERR("MCP response failure, unloading\n");
+                       BNX2X_ERR("MCP response failure, aborting\n");
                        return -EBUSY;
                }
                if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED)
                        return -EBUSY; /* other port in diagnostic mode */
 
        } else {
+               int port = BP_PORT(bp);
+
                DP(NETIF_MSG_IFUP, "NO MCP load counts before us %d, %d, %d\n",
                   load_count[0], load_count[1], load_count[2]);
                load_count[0]++;
-               load_count[1 + BP_PORT(bp)]++;
+               load_count[1 + port]++;
                DP(NETIF_MSG_IFUP, "NO MCP new load counts       %d, %d, %d\n",
                   load_count[0], load_count[1], load_count[2]);
                if (load_count[0] == 1)
                        load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
-               else if (load_count[1 + BP_PORT(bp)] == 1)
+               else if (load_count[1 + port] == 1)
                        load_code = FW_MSG_CODE_DRV_LOAD_PORT;
                else
                        load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION;
@@ -6247,9 +6316,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
                bnx2x_fp(bp, i, disable_tpa) =
                                        ((bp->flags & TPA_ENABLE_FLAG) == 0);
 
-       /* Disable interrupt handling until HW is initialized */
-       atomic_set(&bp->intr_sem, 1);
-
        if (bp->flags & USING_MSIX_FLAG) {
                rc = bnx2x_req_msix_irqs(bp);
                if (rc) {
@@ -6276,17 +6342,14 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
                goto load_error;
        }
 
-       /* Enable interrupt handling */
-       atomic_set(&bp->intr_sem, 0);
-
        /* Setup NIC internals and enable interrupts */
-       bnx2x_nic_init(bp);
+       bnx2x_nic_init(bp, load_code);
 
        /* Send LOAD_DONE command to MCP */
        if (!BP_NOMCP(bp)) {
                load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
                if (!load_code) {
-                       BNX2X_ERR("MCP response failure, unloading\n");
+                       BNX2X_ERR("MCP response failure, aborting\n");
                        rc = -EBUSY;
                        goto load_int_disable;
                }
@@ -6301,11 +6364,12 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
        for_each_queue(bp, i)
                napi_enable(&bnx2x_fp(bp, i, napi));
 
+       /* Enable interrupt handling */
+       atomic_set(&bp->intr_sem, 0);
+
        rc = bnx2x_setup_leading(bp);
        if (rc) {
-#ifdef BNX2X_STOP_ON_ERROR
-               bp->panic = 1;
-#endif
+               BNX2X_ERR("Setup leading failed!\n");
                goto load_stop_netif;
        }
 
@@ -6323,9 +6387,9 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
                }
 
        if (CHIP_IS_E1(bp))
-               bnx2x_set_mac_addr_e1(bp);
+               bnx2x_set_mac_addr_e1(bp, 1);
        else
-               bnx2x_set_mac_addr_e1h(bp);
+               bnx2x_set_mac_addr_e1h(bp, 1);
 
        if (bp->port.pmf)
                bnx2x_initial_phy_init(bp);
@@ -6339,7 +6403,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
                break;
 
        case LOAD_OPEN:
-               /* IRQ is only requested from bnx2x_open */
                netif_start_queue(bp->dev);
                bnx2x_set_rx_mode(bp->dev);
                if (bp->flags & USING_MSIX_FLAG)
@@ -6378,8 +6441,7 @@ load_int_disable:
        /* Free SKBs, SGEs, TPA pool and driver internals */
        bnx2x_free_skbs(bp);
        for_each_queue(bp, i)
-               bnx2x_free_rx_sge_range(bp, bp->fp + i,
-                                       RX_SGE_CNT*NUM_RX_SGE_PAGES);
+               bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
 load_error:
        bnx2x_free_mem(bp);
 
@@ -6411,7 +6473,7 @@ static int bnx2x_stop_multi(struct bnx2x *bp, int index)
        return rc;
 }
 
-static void bnx2x_stop_leading(struct bnx2x *bp)
+static int bnx2x_stop_leading(struct bnx2x *bp)
 {
        u16 dsb_sp_prod_idx;
        /* if the other port is handling traffic,
@@ -6429,7 +6491,7 @@ static void bnx2x_stop_leading(struct bnx2x *bp)
        rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, 0,
                               &(bp->fp[0].state), 1);
        if (rc) /* timeout */
-               return;
+               return rc;
 
        dsb_sp_prod_idx = *bp->dsb_sp_prod;
 
@@ -6441,20 +6503,24 @@ static void bnx2x_stop_leading(struct bnx2x *bp)
           so there is not much to do if this times out
         */
        while (dsb_sp_prod_idx == *bp->dsb_sp_prod) {
-               msleep(1);
                if (!cnt) {
                        DP(NETIF_MSG_IFDOWN, "timeout waiting for port del "
                           "dsb_sp_prod 0x%x != dsb_sp_prod_idx 0x%x\n",
                           *bp->dsb_sp_prod, dsb_sp_prod_idx);
 #ifdef BNX2X_STOP_ON_ERROR
                        bnx2x_panic();
+#else
+                       rc = -EBUSY;
 #endif
                        break;
                }
                cnt--;
+               msleep(1);
        }
        bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
        bp->fp[0].state = BNX2X_FP_STATE_CLOSED;
+
+       return rc;
 }
 
 static void bnx2x_reset_func(struct bnx2x *bp)
@@ -6496,7 +6562,7 @@ static void bnx2x_reset_port(struct bnx2x *bp)
        val = REG_RD(bp, BRB1_REG_PORT_NUM_OCC_BLOCKS_0 + port*4);
        if (val)
                DP(NETIF_MSG_IFDOWN,
-                  "BRB1 is not empty  %d blooks are occupied\n", val);
+                  "BRB1 is not empty  %d blocks are occupied\n", val);
 
        /* TODO: Close Doorbell port? */
 }
@@ -6536,11 +6602,12 @@ static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
        }
 }
 
-/* msut be called with rtnl_lock */
+/* must be called with rtnl_lock */
 static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
 {
+       int port = BP_PORT(bp);
        u32 reset_code = 0;
-       int i, cnt;
+       int i, cnt, rc;
 
        bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
 
@@ -6557,22 +6624,17 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
                 (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
        bnx2x_stats_handle(bp, STATS_EVENT_STOP);
 
-       /* Wait until all fast path tasks complete */
+       /* Wait until tx fast path tasks complete */
        for_each_queue(bp, i) {
                struct bnx2x_fastpath *fp = &bp->fp[i];
 
-#ifdef BNX2X_STOP_ON_ERROR
-#ifdef __powerpc64__
-               DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%lx\n",
-#else
-               DP(NETIF_MSG_IFDOWN, "fp->tpa_queue_used = 0x%llx\n",
-#endif
-                  fp->tpa_queue_used);
-#endif
                cnt = 1000;
                smp_rmb();
-               while (bnx2x_has_work(fp)) {
-                       msleep(1);
+               while (BNX2X_HAS_TX_WORK(fp)) {
+
+                       if (!netif_running(bp->dev))
+                               bnx2x_tx_int(fp, 1000);
+
                        if (!cnt) {
                                BNX2X_ERR("timeout waiting for queue[%d]\n",
                                          i);
@@ -6584,14 +6646,13 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
 #endif
                        }
                        cnt--;
+                       msleep(1);
                        smp_rmb();
                }
        }
 
-       /* Wait until all slow path tasks complete */
-       cnt = 1000;
-       while ((bp->spq_left != MAX_SPQ_PENDING) && cnt--)
-               msleep(1);
+       /* Give HW time to discard old tx messages */
+       msleep(1);
 
        for_each_queue(bp, i)
                napi_disable(&bnx2x_fp(bp, i, napi));
@@ -6601,52 +6662,79 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
        /* Release IRQs */
        bnx2x_free_irq(bp);
 
-       if (bp->flags & NO_WOL_FLAG)
+       if (unload_mode == UNLOAD_NORMAL)
+               reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
+
+       else if (bp->flags & NO_WOL_FLAG) {
                reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP;
+               if (CHIP_IS_E1H(bp))
+                       REG_WR(bp, MISC_REG_E1HMF_MODE, 0);
 
-       else if (bp->wol) {
-               u32 emac_base = BP_PORT(bp) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+       else if (bp->wol) {
+               u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
                u8 *mac_addr = bp->dev->dev_addr;
                u32 val;
-
                /* The mac address is written to entries 1-4 to
                   preserve entry 0 which is used by the PMF */
+               u8 entry = (BP_E1HVN(bp) + 1)*8;
+
                val = (mac_addr[0] << 8) | mac_addr[1];
-               EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + (BP_E1HVN(bp) + 1)*8, val);
+               EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry, val);
 
                val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
                      (mac_addr[4] << 8) | mac_addr[5];
-               EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + (BP_E1HVN(bp) + 1)*8 + 4,
-                       val);
+               EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val);
 
                reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN;
 
        } else
                reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
 
+       if (CHIP_IS_E1(bp)) {
+               struct mac_configuration_cmd *config =
+                                               bnx2x_sp(bp, mcast_config);
+
+               bnx2x_set_mac_addr_e1(bp, 0);
+
+               for (i = 0; i < config->hdr.length_6b; i++)
+                       CAM_INVALIDATE(config->config_table[i]);
+
+               config->hdr.length_6b = i;
+               if (CHIP_REV_IS_SLOW(bp))
+                       config->hdr.offset = BNX2X_MAX_EMUL_MULTI*(1 + port);
+               else
+                       config->hdr.offset = BNX2X_MAX_MULTICAST*(1 + port);
+               config->hdr.client_id = BP_CL_ID(bp);
+               config->hdr.reserved1 = 0;
+
+               bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
+                             U64_HI(bnx2x_sp_mapping(bp, mcast_config)),
+                             U64_LO(bnx2x_sp_mapping(bp, mcast_config)), 0);
+
+       } else { /* E1H */
+               bnx2x_set_mac_addr_e1h(bp, 0);
+
+               for (i = 0; i < MC_HASH_SIZE; i++)
+                       REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+       }
+
+       if (CHIP_IS_E1H(bp))
+               REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
+
        /* Close multi and leading connections
           Completions for ramrods are collected in a synchronous way */
        for_each_nondefault_queue(bp, i)
                if (bnx2x_stop_multi(bp, i))
                        goto unload_error;
 
-       if (CHIP_IS_E1H(bp))
-               REG_WR(bp, NIG_REG_LLH0_FUNC_EN + BP_PORT(bp)*8, 0);
-
-       bnx2x_stop_leading(bp);
-#ifdef BNX2X_STOP_ON_ERROR
-       /* If ramrod completion timed out - break here! */
-       if (bp->panic) {
+       rc = bnx2x_stop_leading(bp);
+       if (rc) {
                BNX2X_ERR("Stop leading failed!\n");
+#ifdef BNX2X_STOP_ON_ERROR
                return -EBUSY;
-       }
+#else
+               goto unload_error;
 #endif
-
-       if ((bp->state != BNX2X_STATE_CLOSING_WAIT4_UNLOAD) ||
-           (bp->fp[0].state != BNX2X_FP_STATE_CLOSED)) {
-               DP(NETIF_MSG_IFDOWN, "failed to close leading properly!  "
-                  "state 0x%x  fp[0].state 0x%x\n",
-                  bp->state, bp->fp[0].state);
        }
 
 unload_error:
@@ -6656,12 +6744,12 @@ unload_error:
                DP(NETIF_MSG_IFDOWN, "NO MCP load counts      %d, %d, %d\n",
                   load_count[0], load_count[1], load_count[2]);
                load_count[0]--;
-               load_count[1 + BP_PORT(bp)]--;
+               load_count[1 + port]--;
                DP(NETIF_MSG_IFDOWN, "NO MCP new load counts  %d, %d, %d\n",
                   load_count[0], load_count[1], load_count[2]);
                if (load_count[0] == 0)
                        reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
-               else if (load_count[1 + BP_PORT(bp)] == 0)
+               else if (load_count[1 + port] == 0)
                        reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
                else
                        reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
@@ -6681,8 +6769,7 @@ unload_error:
        /* Free SKBs, SGEs, TPA pool and driver internals */
        bnx2x_free_skbs(bp);
        for_each_queue(bp, i)
-               bnx2x_free_rx_sge_range(bp, bp->fp + i,
-                                       RX_SGE_CNT*NUM_RX_SGE_PAGES);
+               bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
        bnx2x_free_mem(bp);
 
        bp->state = BNX2X_STATE_CLOSED;
@@ -6733,56 +6820,93 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
                /* Check if it is the UNDI driver
                 * UNDI driver initializes CID offset for normal bell to 0x7
                 */
+               bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
                val = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
                if (val == 0x7) {
                        u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
-                       /* save our func and fw_seq */
+                       /* save our func */
                        int func = BP_FUNC(bp);
-                       u16 fw_seq = bp->fw_seq;
+                       u32 swap_en;
+                       u32 swap_val;
 
                        BNX2X_DEV_INFO("UNDI is active! reset device\n");
 
                        /* try unload UNDI on port 0 */
                        bp->func = 0;
-                       bp->fw_seq = (SHMEM_RD(bp,
-                                            func_mb[bp->func].drv_mb_header) &
-                                     DRV_MSG_SEQ_NUMBER_MASK);
-
+                       bp->fw_seq =
+                              (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
+                               DRV_MSG_SEQ_NUMBER_MASK);
                        reset_code = bnx2x_fw_command(bp, reset_code);
-                       bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
 
                        /* if UNDI is loaded on the other port */
                        if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) {
 
+                               /* send "DONE" for previous unload */
+                               bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+
+                               /* unload UNDI on port 1 */
                                bp->func = 1;
-                               bp->fw_seq = (SHMEM_RD(bp,
-                                            func_mb[bp->func].drv_mb_header) &
-                                             DRV_MSG_SEQ_NUMBER_MASK);
-
-                               bnx2x_fw_command(bp,
-                                            DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS);
-                               bnx2x_fw_command(bp,
-                                                DRV_MSG_CODE_UNLOAD_DONE);
-
-                               /* restore our func and fw_seq */
-                               bp->func = func;
-                               bp->fw_seq = fw_seq;
+                               bp->fw_seq =
+                              (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
+                                       DRV_MSG_SEQ_NUMBER_MASK);
+                               reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
+
+                               bnx2x_fw_command(bp, reset_code);
                        }
 
+                       REG_WR(bp, (BP_PORT(bp) ? HC_REG_CONFIG_1 :
+                                   HC_REG_CONFIG_0), 0x1000);
+
+                       /* close input traffic and wait for it */
+                       /* Do not rcv packets to BRB */
+                       REG_WR(bp,
+                             (BP_PORT(bp) ? NIG_REG_LLH1_BRB1_DRV_MASK :
+                                            NIG_REG_LLH0_BRB1_DRV_MASK), 0x0);
+                       /* Do not direct rcv packets that are not for MCP to
+                        * the BRB */
+                       REG_WR(bp,
+                              (BP_PORT(bp) ? NIG_REG_LLH1_BRB1_NOT_MCP :
+                                             NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
+                       /* clear AEU */
+                       REG_WR(bp,
+                            (BP_PORT(bp) ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
+                                           MISC_REG_AEU_MASK_ATTN_FUNC_0), 0);
+                       msleep(10);
+
+                       /* save NIG port swap info */
+                       swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+                       swap_en = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
                        /* reset device */
                        REG_WR(bp,
                               GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
-                              0xd3ffff7f);
+                              0xd3ffffff);
                        REG_WR(bp,
                               GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
                               0x1403);
+                       /* take the NIG out of reset and restore swap values */
+                       REG_WR(bp,
+                              GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
+                              MISC_REGISTERS_RESET_REG_1_RST_NIG);
+                       REG_WR(bp, NIG_REG_PORT_SWAP, swap_val);
+                       REG_WR(bp, NIG_REG_STRAP_OVERRIDE, swap_en);
+
+                       /* send unload done to the MCP */
+                       bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+
+                       /* restore our func and fw_seq */
+                       bp->func = func;
+                       bp->fw_seq =
+                              (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
+                               DRV_MSG_SEQ_NUMBER_MASK);
                }
+               bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
        }
 }
 
 static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
 {
        u32 val, val2, val3, val4, id;
+       u16 pmc;
 
        /* Get the chip revision id and number. */
        /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
@@ -6840,8 +6964,16 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
                BNX2X_ERR("This driver needs bc_ver %X but found %X,"
                          " please upgrade BC\n", BNX2X_BC_VER, val);
        }
-       BNX2X_DEV_INFO("%sWoL Capable\n",
-                      (bp->flags & NO_WOL_FLAG)? "Not " : "");
+
+       if (BP_E1HVN(bp) == 0) {
+               pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc);
+               bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG;
+       } else {
+               /* no WOL capability for E1HVN != 0 */
+               bp->flags |= NO_WOL_FLAG;
+       }
+       BNX2X_DEV_INFO("%sWoL capable\n",
+                      (bp->flags & NO_WOL_FLAG) ? "Not " : "");
 
        val = SHMEM_RD(bp, dev_info.shared_hw_config.part_num);
        val2 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[4]);
@@ -7274,9 +7406,8 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
                bp->mf_config =
                        SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
 
-               val =
-                  (SHMEM_RD(bp, mf_cfg.func_mf_config[func].e1hov_tag) &
-                   FUNC_MF_CFG_E1HOV_TAG_MASK);
+               val = (SHMEM_RD(bp, mf_cfg.func_mf_config[func].e1hov_tag) &
+                      FUNC_MF_CFG_E1HOV_TAG_MASK);
                if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
 
                        bp->e1hov = val;
@@ -7324,7 +7455,7 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
 
        if (BP_NOMCP(bp)) {
                /* only supposed to happen on emulation/FPGA */
-               BNX2X_ERR("warning rendom MAC workaround active\n");
+               BNX2X_ERR("warning random MAC workaround active\n");
                random_ether_addr(bp->dev->dev_addr);
                memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
        }
@@ -7337,8 +7468,8 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
        int func = BP_FUNC(bp);
        int rc;
 
-       if (nomcp)
-               bp->flags |= NO_MCP_FLAG;
+       /* Disable interrupt handling until HW is initialized */
+       atomic_set(&bp->intr_sem, 1);
 
        mutex_init(&bp->port.phy_mutex);
 
@@ -7377,8 +7508,6 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
        bp->tx_ticks = 50;
        bp->rx_ticks = 25;
 
-       bp->stats_ticks = 1000000 & 0xffff00;
-
        bp->timer_interval = (CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ);
        bp->current_interval = (poll ? poll : bp->timer_interval);
 
@@ -7628,25 +7757,25 @@ static void bnx2x_get_drvinfo(struct net_device *dev,
                              struct ethtool_drvinfo *info)
 {
        struct bnx2x *bp = netdev_priv(dev);
-       char phy_fw_ver[PHY_FW_VER_LEN];
+       u8 phy_fw_ver[PHY_FW_VER_LEN];
 
        strcpy(info->driver, DRV_MODULE_NAME);
        strcpy(info->version, DRV_MODULE_VERSION);
 
        phy_fw_ver[0] = '\0';
        if (bp->port.pmf) {
-               bnx2x_phy_hw_lock(bp);
+               bnx2x_acquire_phy_lock(bp);
                bnx2x_get_ext_phy_fw_version(&bp->link_params,
                                             (bp->state != BNX2X_STATE_CLOSED),
                                             phy_fw_ver, PHY_FW_VER_LEN);
-               bnx2x_phy_hw_unlock(bp);
+               bnx2x_release_phy_lock(bp);
        }
 
-       snprintf(info->fw_version, 32, "%d.%d.%d:%d BC:%x%s%s",
-                BCM_5710_FW_MAJOR_VERSION, BCM_5710_FW_MINOR_VERSION,
-                BCM_5710_FW_REVISION_VERSION,
-                BCM_5710_FW_COMPILE_FLAGS, bp->common.bc_ver,
-                ((phy_fw_ver[0] != '\0')? " PHY:":""), phy_fw_ver);
+       snprintf(info->fw_version, 32, "BC:%d.%d.%d%s%s",
+                (bp->common.bc_ver & 0xff0000) >> 16,
+                (bp->common.bc_ver & 0xff00) >> 8,
+                (bp->common.bc_ver & 0xff),
+                ((phy_fw_ver[0] != '\0') ? " PHY:" : ""), phy_fw_ver);
        strcpy(info->bus_info, pci_name(bp->pdev));
        info->n_stats = BNX2X_NUM_STATS;
        info->testinfo_len = BNX2X_NUM_TESTS;
@@ -8097,7 +8226,7 @@ static int bnx2x_set_eeprom(struct net_device *dev,
        if (eeprom->magic == 0x00504859)
                if (bp->port.pmf) {
 
-                       bnx2x_phy_hw_lock(bp);
+                       bnx2x_acquire_phy_lock(bp);
                        rc = bnx2x_flash_download(bp, BP_PORT(bp),
                                             bp->link_params.ext_phy_config,
                                             (bp->state != BNX2X_STATE_CLOSED),
@@ -8109,7 +8238,7 @@ static int bnx2x_set_eeprom(struct net_device *dev,
                                rc |= bnx2x_phy_init(&bp->link_params,
                                                     &bp->link_vars);
                        }
-                       bnx2x_phy_hw_unlock(bp);
+                       bnx2x_release_phy_lock(bp);
 
                } else /* Only the PMF can access the PHY */
                        return -EINVAL;
@@ -8128,7 +8257,6 @@ static int bnx2x_get_coalesce(struct net_device *dev,
 
        coal->rx_coalesce_usecs = bp->rx_ticks;
        coal->tx_coalesce_usecs = bp->tx_ticks;
-       coal->stats_block_coalesce_usecs = bp->stats_ticks;
 
        return 0;
 }
@@ -8146,44 +8274,12 @@ static int bnx2x_set_coalesce(struct net_device *dev,
        if (bp->tx_ticks > 0x3000)
                bp->tx_ticks = 0x3000;
 
-       bp->stats_ticks = coal->stats_block_coalesce_usecs;
-       if (bp->stats_ticks > 0xffff00)
-               bp->stats_ticks = 0xffff00;
-       bp->stats_ticks &= 0xffff00;
-
        if (netif_running(dev))
                bnx2x_update_coalesce(bp);
 
        return 0;
 }
 
-static int bnx2x_set_flags(struct net_device *dev, u32 data)
-{
-       struct bnx2x *bp = netdev_priv(dev);
-       int changed = 0;
-       int rc = 0;
-
-       if (data & ETH_FLAG_LRO) {
-               if (!(dev->features & NETIF_F_LRO)) {
-                       dev->features |= NETIF_F_LRO;
-                       bp->flags |= TPA_ENABLE_FLAG;
-                       changed = 1;
-               }
-
-       } else if (dev->features & NETIF_F_LRO) {
-               dev->features &= ~NETIF_F_LRO;
-               bp->flags &= ~TPA_ENABLE_FLAG;
-               changed = 1;
-       }
-
-       if (changed && netif_running(dev)) {
-               bnx2x_nic_unload(bp, UNLOAD_NORMAL);
-               rc = bnx2x_nic_load(bp, LOAD_NORMAL);
-       }
-
-       return rc;
-}
-
 static void bnx2x_get_ringparam(struct net_device *dev,
                                struct ethtool_ringparam *ering)
 {
@@ -8266,7 +8362,7 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
 
        if (epause->autoneg) {
                if (!(bp->port.supported & SUPPORTED_Autoneg)) {
-                       DP(NETIF_MSG_LINK, "Autoneg not supported\n");
+                       DP(NETIF_MSG_LINK, "autoneg not supported\n");
                        return -EINVAL;
                }
 
@@ -8285,6 +8381,34 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
        return 0;
 }
 
+static int bnx2x_set_flags(struct net_device *dev, u32 data)
+{
+       struct bnx2x *bp = netdev_priv(dev);
+       int changed = 0;
+       int rc = 0;
+
+       /* TPA requires Rx CSUM offloading */
+       if ((data & ETH_FLAG_LRO) && bp->rx_csum) {
+               if (!(dev->features & NETIF_F_LRO)) {
+                       dev->features |= NETIF_F_LRO;
+                       bp->flags |= TPA_ENABLE_FLAG;
+                       changed = 1;
+               }
+
+       } else if (dev->features & NETIF_F_LRO) {
+               dev->features &= ~NETIF_F_LRO;
+               bp->flags &= ~TPA_ENABLE_FLAG;
+               changed = 1;
+       }
+
+       if (changed && netif_running(dev)) {
+               bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+               rc = bnx2x_nic_load(bp, LOAD_NORMAL);
+       }
+
+       return rc;
+}
+
 static u32 bnx2x_get_rx_csum(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
@@ -8295,9 +8419,19 @@ static u32 bnx2x_get_rx_csum(struct net_device *dev)
 static int bnx2x_set_rx_csum(struct net_device *dev, u32 data)
 {
        struct bnx2x *bp = netdev_priv(dev);
+       int rc = 0;
 
        bp->rx_csum = data;
-       return 0;
+
+       /* Disable TPA, when Rx CSUM is disabled. Otherwise all
+          TPA'ed packets will be discarded due to wrong TCP CSUM */
+       if (!data) {
+               u32 flags = ethtool_op_get_flags(dev);
+
+               rc = bnx2x_set_flags(dev, (flags & ~ETH_FLAG_LRO));
+       }
+
+       return rc;
 }
 
 static int bnx2x_set_tso(struct net_device *dev, u32 data)
@@ -8335,6 +8469,7 @@ static int bnx2x_test_registers(struct bnx2x *bp)
 {
        int idx, i, rc = -ENODEV;
        u32 wr_val = 0;
+       int port = BP_PORT(bp);
        static const struct {
                u32  offset0;
                u32  offset1;
@@ -8400,7 +8535,6 @@ static int bnx2x_test_registers(struct bnx2x *bp)
 
                for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) {
                        u32 offset, mask, save_val, val;
-                       int port = BP_PORT(bp);
 
                        offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1;
                        mask = reg_tbl[i].mask;
@@ -8446,16 +8580,17 @@ static int bnx2x_test_memory(struct bnx2x *bp)
        static const struct {
                char *name;
                u32 offset;
-               u32 mask;
+               u32 e1_mask;
+               u32 e1h_mask;
        } prty_tbl[] = {
-               { "CCM_REG_CCM_PRTY_STS",     CCM_REG_CCM_PRTY_STS,     0 },
-               { "CFC_REG_CFC_PRTY_STS",     CFC_REG_CFC_PRTY_STS,     0 },
-               { "DMAE_REG_DMAE_PRTY_STS",   DMAE_REG_DMAE_PRTY_STS,   0 },
-               { "TCM_REG_TCM_PRTY_STS",     TCM_REG_TCM_PRTY_STS,     0 },
-               { "UCM_REG_UCM_PRTY_STS",     UCM_REG_UCM_PRTY_STS,     0 },
-               { "XCM_REG_XCM_PRTY_STS",     XCM_REG_XCM_PRTY_STS,     0x1 },
-
-               { NULL, 0xffffffff, 0 }
+               { "CCM_PRTY_STS",  CCM_REG_CCM_PRTY_STS,   0x3ffc0, 0 },
+               { "CFC_PRTY_STS",  CFC_REG_CFC_PRTY_STS,   0x2,     0x2 },
+               { "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0,       0 },
+               { "TCM_PRTY_STS",  TCM_REG_TCM_PRTY_STS,   0x3ffc0, 0 },
+               { "UCM_PRTY_STS",  UCM_REG_UCM_PRTY_STS,   0x3ffc0, 0 },
+               { "XCM_PRTY_STS",  XCM_REG_XCM_PRTY_STS,   0x3ffc1, 0 },
+
+               { NULL, 0xffffffff, 0, 0 }
        };
 
        if (!netif_running(bp->dev))
@@ -8469,7 +8604,8 @@ static int bnx2x_test_memory(struct bnx2x *bp)
        /* Check the parity status */
        for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
                val = REG_RD(bp, prty_tbl[i].offset);
-               if (val & ~(prty_tbl[i].mask)) {
+               if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
+                   (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask)))) {
                        DP(NETIF_MSG_HW,
                           "%s is 0x%x\n", prty_tbl[i].name, val);
                        goto test_mem_exit;
@@ -8539,15 +8675,15 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
 
        if (loopback_mode == BNX2X_MAC_LOOPBACK) {
                bp->link_params.loopback_mode = LOOPBACK_BMAC;
-               bnx2x_phy_hw_lock(bp);
+               bnx2x_acquire_phy_lock(bp);
                bnx2x_phy_init(&bp->link_params, &bp->link_vars);
-               bnx2x_phy_hw_unlock(bp);
+               bnx2x_release_phy_lock(bp);
 
        } else if (loopback_mode == BNX2X_PHY_LOOPBACK) {
                bp->link_params.loopback_mode = LOOPBACK_XGXS_10;
-               bnx2x_phy_hw_lock(bp);
+               bnx2x_acquire_phy_lock(bp);
                bnx2x_phy_init(&bp->link_params, &bp->link_vars);
-               bnx2x_phy_hw_unlock(bp);
+               bnx2x_release_phy_lock(bp);
                /* wait until link state is restored */
                bnx2x_wait_for_link(bp, link_up);
 
@@ -8771,7 +8907,7 @@ static void bnx2x_self_test(struct net_device *dev,
        if (!netif_running(dev))
                return;
 
-       /* offline tests are not suppoerted in MF mode */
+       /* offline tests are not supported in MF mode */
        if (IS_E1HMF(bp))
                etest->flags &= ~ETH_TEST_FL_OFFLINE;
 
@@ -8827,76 +8963,99 @@ static const struct {
        long offset;
        int size;
        u32 flags;
-       char string[ETH_GSTRING_LEN];
+#define STATS_FLAGS_PORT               1
+#define STATS_FLAGS_FUNC               2
+       u8 string[ETH_GSTRING_LEN];
 } bnx2x_stats_arr[BNX2X_NUM_STATS] = {
-/* 1 */        { STATS_OFFSET32(valid_bytes_received_hi),     8, 1, "rx_bytes" },
-       { STATS_OFFSET32(error_bytes_received_hi),     8, 1, "rx_error_bytes" },
-       { STATS_OFFSET32(total_bytes_transmitted_hi),  8, 1, "tx_bytes" },
-       { STATS_OFFSET32(tx_stat_ifhcoutbadoctets_hi), 8, 0, "tx_error_bytes" },
+/* 1 */        { STATS_OFFSET32(valid_bytes_received_hi),
+                               8, STATS_FLAGS_FUNC, "rx_bytes" },
+       { STATS_OFFSET32(error_bytes_received_hi),
+                               8, STATS_FLAGS_FUNC, "rx_error_bytes" },
+       { STATS_OFFSET32(total_bytes_transmitted_hi),
+                               8, STATS_FLAGS_FUNC, "tx_bytes" },
+       { STATS_OFFSET32(tx_stat_ifhcoutbadoctets_hi),
+                               8, STATS_FLAGS_PORT, "tx_error_bytes" },
        { STATS_OFFSET32(total_unicast_packets_received_hi),
-                                               8, 1, "rx_ucast_packets" },
+                               8, STATS_FLAGS_FUNC, "rx_ucast_packets" },
        { STATS_OFFSET32(total_multicast_packets_received_hi),
-                                               8, 1, "rx_mcast_packets" },
+                               8, STATS_FLAGS_FUNC, "rx_mcast_packets" },
        { STATS_OFFSET32(total_broadcast_packets_received_hi),
-                                               8, 1, "rx_bcast_packets" },
+                               8, STATS_FLAGS_FUNC, "rx_bcast_packets" },
        { STATS_OFFSET32(total_unicast_packets_transmitted_hi),
-                                               8, 1, "tx_packets" },
+                               8, STATS_FLAGS_FUNC, "tx_packets" },
        { STATS_OFFSET32(tx_stat_dot3statsinternalmactransmiterrors_hi),
-                                               8, 0, "tx_mac_errors" },
+                               8, STATS_FLAGS_PORT, "tx_mac_errors" },
 /* 10 */{ STATS_OFFSET32(rx_stat_dot3statscarriersenseerrors_hi),
-                                               8, 0, "tx_carrier_errors" },
+                               8, STATS_FLAGS_PORT, "tx_carrier_errors" },
        { STATS_OFFSET32(rx_stat_dot3statsfcserrors_hi),
-                                               8, 0, "rx_crc_errors" },
+                               8, STATS_FLAGS_PORT, "rx_crc_errors" },
        { STATS_OFFSET32(rx_stat_dot3statsalignmenterrors_hi),
-                                               8, 0, "rx_align_errors" },
+                               8, STATS_FLAGS_PORT, "rx_align_errors" },
        { STATS_OFFSET32(tx_stat_dot3statssinglecollisionframes_hi),
-                                               8, 0, "tx_single_collisions" },
+                               8, STATS_FLAGS_PORT, "tx_single_collisions" },
        { STATS_OFFSET32(tx_stat_dot3statsmultiplecollisionframes_hi),
-                                               8, 0, "tx_multi_collisions" },
+                               8, STATS_FLAGS_PORT, "tx_multi_collisions" },
        { STATS_OFFSET32(tx_stat_dot3statsdeferredtransmissions_hi),
-                                               8, 0, "tx_deferred" },
+                               8, STATS_FLAGS_PORT, "tx_deferred" },
        { STATS_OFFSET32(tx_stat_dot3statsexcessivecollisions_hi),
-                                               8, 0, "tx_excess_collisions" },
+                               8, STATS_FLAGS_PORT, "tx_excess_collisions" },
        { STATS_OFFSET32(tx_stat_dot3statslatecollisions_hi),
-                                               8, 0, "tx_late_collisions" },
+                               8, STATS_FLAGS_PORT, "tx_late_collisions" },
        { STATS_OFFSET32(tx_stat_etherstatscollisions_hi),
-                                               8, 0, "tx_total_collisions" },
+                               8, STATS_FLAGS_PORT, "tx_total_collisions" },
        { STATS_OFFSET32(rx_stat_etherstatsfragments_hi),
-                                               8, 0, "rx_fragments" },
-/* 20 */{ STATS_OFFSET32(rx_stat_etherstatsjabbers_hi), 8, 0, "rx_jabbers" },
+                               8, STATS_FLAGS_PORT, "rx_fragments" },
+/* 20 */{ STATS_OFFSET32(rx_stat_etherstatsjabbers_hi),
+                               8, STATS_FLAGS_PORT, "rx_jabbers" },
        { STATS_OFFSET32(rx_stat_etherstatsundersizepkts_hi),
-                                               8, 0, "rx_undersize_packets" },
+                               8, STATS_FLAGS_PORT, "rx_undersize_packets" },
        { STATS_OFFSET32(jabber_packets_received),
-                                               4, 1, "rx_oversize_packets" },
+                               4, STATS_FLAGS_FUNC, "rx_oversize_packets" },
        { STATS_OFFSET32(tx_stat_etherstatspkts64octets_hi),
-                                               8, 0, "tx_64_byte_packets" },
+                               8, STATS_FLAGS_PORT, "tx_64_byte_packets" },
        { STATS_OFFSET32(tx_stat_etherstatspkts65octetsto127octets_hi),
-                                       8, 0, "tx_65_to_127_byte_packets" },
+                       8, STATS_FLAGS_PORT, "tx_65_to_127_byte_packets" },
        { STATS_OFFSET32(tx_stat_etherstatspkts128octetsto255octets_hi),
-                                       8, 0, "tx_128_to_255_byte_packets" },
+                       8, STATS_FLAGS_PORT, "tx_128_to_255_byte_packets" },
        { STATS_OFFSET32(tx_stat_etherstatspkts256octetsto511octets_hi),
-                                       8, 0, "tx_256_to_511_byte_packets" },
+                       8, STATS_FLAGS_PORT, "tx_256_to_511_byte_packets" },
        { STATS_OFFSET32(tx_stat_etherstatspkts512octetsto1023octets_hi),
-                                       8, 0, "tx_512_to_1023_byte_packets" },
+                       8, STATS_FLAGS_PORT, "tx_512_to_1023_byte_packets" },
        { STATS_OFFSET32(etherstatspkts1024octetsto1522octets_hi),
-                                       8, 0, "tx_1024_to_1522_byte_packets" },
+                       8, STATS_FLAGS_PORT, "tx_1024_to_1522_byte_packets" },
        { STATS_OFFSET32(etherstatspktsover1522octets_hi),
-                                       8, 0, "tx_1523_to_9022_byte_packets" },
+                       8, STATS_FLAGS_PORT, "tx_1523_to_9022_byte_packets" },
 /* 30 */{ STATS_OFFSET32(rx_stat_xonpauseframesreceived_hi),
-                                               8, 0, "rx_xon_frames" },
+                               8, STATS_FLAGS_PORT, "rx_xon_frames" },
        { STATS_OFFSET32(rx_stat_xoffpauseframesreceived_hi),
-                                               8, 0, "rx_xoff_frames" },
-       { STATS_OFFSET32(tx_stat_outxonsent_hi),  8, 0, "tx_xon_frames" },
-       { STATS_OFFSET32(tx_stat_outxoffsent_hi), 8, 0, "tx_xoff_frames" },
+                               8, STATS_FLAGS_PORT, "rx_xoff_frames" },
+       { STATS_OFFSET32(tx_stat_outxonsent_hi),
+                               8, STATS_FLAGS_PORT, "tx_xon_frames" },
+       { STATS_OFFSET32(tx_stat_outxoffsent_hi),
+                               8, STATS_FLAGS_PORT, "tx_xoff_frames" },
        { STATS_OFFSET32(rx_stat_maccontrolframesreceived_hi),
-                                               8, 0, "rx_mac_ctrl_frames" },
-       { STATS_OFFSET32(mac_filter_discard),   4, 1, "rx_filtered_packets" },
-       { STATS_OFFSET32(no_buff_discard),      4, 1, "rx_discards" },
-       { STATS_OFFSET32(xxoverflow_discard),   4, 1, "rx_fw_discards" },
-       { STATS_OFFSET32(brb_drop_hi),          8, 1, "brb_discard" },
-/* 39 */{ STATS_OFFSET32(brb_truncate_discard), 8, 1, "brb_truncate" }
+                               8, STATS_FLAGS_PORT, "rx_mac_ctrl_frames" },
+       { STATS_OFFSET32(mac_filter_discard),
+                               4, STATS_FLAGS_PORT, "rx_filtered_packets" },
+       { STATS_OFFSET32(no_buff_discard),
+                               4, STATS_FLAGS_FUNC, "rx_discards" },
+       { STATS_OFFSET32(xxoverflow_discard),
+                               4, STATS_FLAGS_PORT, "rx_fw_discards" },
+       { STATS_OFFSET32(brb_drop_hi),
+                               8, STATS_FLAGS_PORT, "brb_discard" },
+       { STATS_OFFSET32(brb_truncate_hi),
+                               8, STATS_FLAGS_PORT, "brb_truncate" },
+/* 40 */{ STATS_OFFSET32(rx_err_discard_pkt),
+                               4, STATS_FLAGS_FUNC, "rx_phy_ip_err_discards"},
+       { STATS_OFFSET32(rx_skb_alloc_failed),
+                               4, STATS_FLAGS_FUNC, "rx_skb_alloc_discard" },
+/* 42 */{ STATS_OFFSET32(hw_csum_err),
+                               4, STATS_FLAGS_FUNC, "rx_csum_offload_errors" }
 };
 
+#define IS_NOT_E1HMF_STAT(bp, i) \
+               (IS_E1HMF(bp) && (bnx2x_stats_arr[i].flags & STATS_FLAGS_PORT))
+
 static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
 {
        struct bnx2x *bp = netdev_priv(dev);
@@ -8905,7 +9064,7 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
        switch (stringset) {
        case ETH_SS_STATS:
                for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
-                       if (IS_E1HMF(bp) && (!bnx2x_stats_arr[i].flags))
+                       if (IS_NOT_E1HMF_STAT(bp, i))
                                continue;
                        strcpy(buf + j*ETH_GSTRING_LEN,
                               bnx2x_stats_arr[i].string);
@@ -8925,7 +9084,7 @@ static int bnx2x_get_stats_count(struct net_device *dev)
        int i, num_stats = 0;
 
        for (i = 0; i < BNX2X_NUM_STATS; i++) {
-               if (IS_E1HMF(bp) && (!bnx2x_stats_arr[i].flags))
+               if (IS_NOT_E1HMF_STAT(bp, i))
                        continue;
                num_stats++;
        }
@@ -8940,7 +9099,7 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
        int i, j;
 
        for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
-               if (IS_E1HMF(bp) && (!bnx2x_stats_arr[i].flags))
+               if (IS_NOT_E1HMF_STAT(bp, i))
                        continue;
 
                if (bnx2x_stats_arr[i].size == 0) {
@@ -9057,7 +9216,7 @@ static int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
                                       PCI_PM_CTRL_PME_STATUS));
 
                if (pmcsr & PCI_PM_CTRL_STATE_MASK)
-               /* delay required during transition out of D3hot */
+                       /* delay required during transition out of D3hot */
                        msleep(20);
                break;
 
@@ -9104,17 +9263,16 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
 
        bnx2x_update_fpsb_idx(fp);
 
-       if ((fp->tx_pkt_prod != le16_to_cpu(*fp->tx_cons_sb)) ||
-           (fp->tx_pkt_prod != fp->tx_pkt_cons))
+       if (BNX2X_HAS_TX_WORK(fp))
                bnx2x_tx_int(fp, budget);
 
-       if (le16_to_cpu(*fp->rx_cons_sb) != fp->rx_comp_cons)
+       if (BNX2X_HAS_RX_WORK(fp))
                work_done = bnx2x_rx_int(fp, budget);
 
-       rmb(); /* bnx2x_has_work() reads the status block */
+       rmb(); /* BNX2X_HAS_WORK() reads the status block */
 
        /* must not complete if we consumed full budget */
-       if ((work_done < budget) && !bnx2x_has_work(fp)) {
+       if ((work_done < budget) && !BNX2X_HAS_WORK(fp)) {
 
 #ifdef BNX2X_STOP_ON_ERROR
 poll_panic:
@@ -9131,7 +9289,7 @@ poll_panic:
 
 
 /* we split the first BD into headers and data BDs
- * to ease the pain of our fellow micocode engineers
+ * to ease the pain of our fellow microcode engineers
  * we use one mapping for both BDs
  * So far this has only been observed to happen
  * in Other Operating Systems(TM)
@@ -9238,7 +9396,7 @@ static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb,
                        /* Check if LSO packet needs to be copied:
                           3 = 1 (for headers BD) + 2 (for PBD and last BD) */
                        int wnd_size = MAX_FETCH_BD - 3;
-                       /* Number of widnows to check */
+                       /* Number of windows to check */
                        int num_wnds = skb_shinfo(skb)->nr_frags - wnd_size;
                        int wnd_idx = 0;
                        int frag_idx = 0;
@@ -9340,7 +9498,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
           skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
           ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type);
 
-       /* First, check if we need to linearaize the skb
+       /* First, check if we need to linearize the skb
           (due to FW restrictions) */
        if (bnx2x_pkt_req_lin(bp, skb, xmit_type)) {
                /* Statistics of linearization */
@@ -9349,7 +9507,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        DP(NETIF_MSG_TX_QUEUED, "SKB linearization failed - "
                           "silently dropping this SKB\n");
                        dev_kfree_skb_any(skb);
-                       return 0;
+                       return NETDEV_TX_OK;
                }
        }
 
@@ -9372,7 +9530,8 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        tx_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
        tx_bd->general_data = (UNICAST_ADDRESS <<
                               ETH_TX_BD_ETH_ADDR_TYPE_SHIFT);
-       tx_bd->general_data |= 1; /* header nbd */
+       /* header nbd */
+       tx_bd->general_data |= (1 << ETH_TX_BD_HDR_NBDS_SHIFT);
 
        /* remember the first BD of the packet */
        tx_buf->first_bd = fp->tx_bd_prod;
@@ -9451,7 +9610,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        tx_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
        tx_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
-       nbd = skb_shinfo(skb)->nr_frags + ((pbd == NULL)? 1 : 2);
+       nbd = skb_shinfo(skb)->nr_frags + ((pbd == NULL) ? 1 : 2);
        tx_bd->nbd = cpu_to_le16(nbd);
        tx_bd->nbytes = cpu_to_le16(skb_headlen(skb));
 
@@ -9721,9 +9880,9 @@ static int bnx2x_change_mac_addr(struct net_device *dev, void *p)
        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
        if (netif_running(dev)) {
                if (CHIP_IS_E1(bp))
-                       bnx2x_set_mac_addr_e1(bp);
+                       bnx2x_set_mac_addr_e1(bp, 1);
                else
-                       bnx2x_set_mac_addr_e1h(bp);
+                       bnx2x_set_mac_addr_e1h(bp, 1);
        }
 
        return 0;
@@ -9734,6 +9893,7 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        struct mii_ioctl_data *data = if_mii(ifr);
        struct bnx2x *bp = netdev_priv(dev);
+       int port = BP_PORT(bp);
        int err;
 
        switch (cmd) {
@@ -9749,7 +9909,7 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                        return -EAGAIN;
 
                mutex_lock(&bp->port.phy_mutex);
-               err = bnx2x_cl45_read(bp, BP_PORT(bp), 0, bp->port.phy_addr,
+               err = bnx2x_cl45_read(bp, port, 0, bp->port.phy_addr,
                                      DEFAULT_PHY_DEV_ADDR,
                                      (data->reg_num & 0x1f), &mii_regval);
                data->val_out = mii_regval;
@@ -9765,7 +9925,7 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                        return -EAGAIN;
 
                mutex_lock(&bp->port.phy_mutex);
-               err = bnx2x_cl45_write(bp, BP_PORT(bp), 0, bp->port.phy_addr,
+               err = bnx2x_cl45_write(bp, port, 0, bp->port.phy_addr,
                                       DEFAULT_PHY_DEV_ADDR,
                                       (data->reg_num & 0x1f), data->val_in);
                mutex_unlock(&bp->port.phy_mutex);
@@ -10141,7 +10301,7 @@ static int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
 
        netif_device_detach(dev);
 
-       bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+       bnx2x_nic_unload(bp, UNLOAD_CLOSE);
 
        bnx2x_set_power_state(bp, pci_choose_state(pdev, state));
 
@@ -10174,7 +10334,7 @@ static int bnx2x_resume(struct pci_dev *pdev)
        bnx2x_set_power_state(bp, PCI_D0);
        netif_device_attach(dev);
 
-       rc = bnx2x_nic_load(bp, LOAD_NORMAL);
+       rc = bnx2x_nic_load(bp, LOAD_OPEN);
 
        rtnl_unlock();
 
index 15c9a99467246ec9b3c58d4b175c0d2ae5fe0f45..a67b0c358ae4a903f3d4c1517ea786b6613b8198 100644 (file)
@@ -6,7 +6,7 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
- * The registers description starts with the regsister Access type followed
+ * The registers description starts with the register Access type followed
  * by size in bits. For example [RW 32]. The access types are:
  * R  - Read only
  * RC - Clear on read
@@ -49,7 +49,7 @@
 /* [RW 10] Write client 0: Assert pause threshold. */
 #define BRB1_REG_PAUSE_LOW_THRESHOLD_0                          0x60068
 #define BRB1_REG_PAUSE_LOW_THRESHOLD_1                          0x6006c
-/* [R 24] The number of full blocks occpied by port. */
+/* [R 24] The number of full blocks occupied by port. */
 #define BRB1_REG_PORT_NUM_OCC_BLOCKS_0                          0x60094
 /* [RW 1] Reset the design by software. */
 #define BRB1_REG_SOFT_RESET                                     0x600dc
 #define HC_REG_ATTN_MSG1_ADDR_L                                 0x108020
 #define HC_REG_ATTN_NUM_P0                                      0x108038
 #define HC_REG_ATTN_NUM_P1                                      0x10803c
+#define HC_REG_COMMAND_REG                                      0x108180
 #define HC_REG_CONFIG_0                                         0x108000
 #define HC_REG_CONFIG_1                                         0x108004
 #define HC_REG_FUNC_NUM_P0                                      0x1080ac
    be asserted). */
 #define MISC_REG_DRIVER_CONTROL_16                              0xa5f0
 #define MISC_REG_DRIVER_CONTROL_16_SIZE                         2
+/* [RW 32] The following driver registers(1...16) represent 16 drivers and
+   32 clients. Each client can be controlled by one driver only. One in each
+   bit represent that this driver control the appropriate client (Ex: bit 5
+   is set means this driver control client number 5). addr1 = set; addr0 =
+   clear; read from both addresses will give the same result = status. write
+   to address 1 will set a request to control all the clients that their
+   appropriate bit (in the write command) is set. if the client is free (the
+   appropriate bit in all the other drivers is clear) one will be written to
+   that driver register; if the client isn't free the bit will remain zero.
+   if the appropriate bit is set (the driver request to gain control on a
+   client it already controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW
+   interrupt will be asserted). write to address 0 will set a request to
+   free all the clients that their appropriate bit (in the write command) is
+   set. if the appropriate bit is clear (the driver request to free a client
+   it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will
+   be asserted). */
+#define MISC_REG_DRIVER_CONTROL_7                               0xa3c8
 /* [RW 1] e1hmf for WOL. If clr WOL signal o the PXP will be send on bit 0
    only. */
 #define MISC_REG_E1HMF_MODE                                     0xa5f8
 #define MISC_REG_GPIO                                           0xa490
 /* [R 28] this field hold the last information that caused reserved
    attention. bits [19:0] - address; [22:20] function; [23] reserved;
-   [27:24] the master thatcaused the attention - according to the following
+   [27:24] the master that caused the attention - according to the following
    encodeing:1 = pxp; 2 = mcp; 3 = usdm; 4 = tsdm; 5 = xsdm; 6 = csdm; 7 =
    dbu; 8 = dmae */
 #define MISC_REG_GRC_RSV_ATTN                                   0xa3c0
 /* [R 28] this field hold the last information that caused timeout
    attention. bits [19:0] - address; [22:20] function; [23] reserved;
-   [27:24] the master thatcaused the attention - according to the following
+   [27:24] the master that caused the attention - according to the following
    encodeing:1 = pxp; 2 = mcp; 3 = usdm; 4 = tsdm; 5 = xsdm; 6 = csdm; 7 =
    dbu; 8 = dmae */
 #define MISC_REG_GRC_TIMEOUT_ATTN                               0xa3c4
 /* [RW 8] init credit counter for port0 in LLH */
 #define NIG_REG_LLH0_XCM_INIT_CREDIT                            0x10554
 #define NIG_REG_LLH0_XCM_MASK                                   0x10130
+#define NIG_REG_LLH1_BRB1_DRV_MASK                              0x10248
 /* [RW 1] send to BRB1 if no match on any of RMP rules. */
 #define NIG_REG_LLH1_BRB1_NOT_MCP                               0x102dc
 /* [RW 2] Determine the classification participants. 0: no classification.1:
 /* [R 32] Rx statistics : In user packets discarded due to BRB backpressure
    for port0 */
 #define NIG_REG_STAT0_BRB_DISCARD                               0x105f0
+/* [R 32] Rx statistics : In user packets truncated due to BRB backpressure
+   for port0 */
+#define NIG_REG_STAT0_BRB_TRUNCATE                              0x105f8
 /* [WB_R 36] Tx statistics : Number of packets from emac0 or bmac0 that
    between 1024 and 1522 bytes for port0 */
 #define NIG_REG_STAT0_EGRESS_MAC_PKT0                           0x10750
 /* [RW 3] page size in L2P table for QM module; -4k; -8k; -16k; -32k; -64k;
    -128k */
 #define PXP2_REG_RQ_QM_P_SIZE                                   0x120050
-/* [RW 1] 1' indicates that the RBC has finished configurating the PSWRQ */
+/* [RW 1] 1' indicates that the RBC has finished configuring the PSWRQ */
 #define PXP2_REG_RQ_RBC_DONE                                    0x1201b0
 /* [RW 3] Max burst size filed for read requests port 0; 000 - 128B;
    001:256B; 010: 512B; 11:1K:100:2K; 01:4K */
 /* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
    buffer reaches this number has_payload will be asserted */
 #define PXP2_REG_WR_DMAE_MPS                                    0x1205ec
-/* [RW 10] if Number of entries in dmae fifo will be higer than this
+/* [RW 10] if Number of entries in dmae fifo will be higher than this
    threshold then has_payload indication will be asserted; the default value
    should be equal to &gt;  write MBS size! */
 #define PXP2_REG_WR_DMAE_TH                                     0x120368
 /* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
    buffer reaches this number has_payload will be asserted */
 #define PXP2_REG_WR_TSDM_MPS                                    0x1205d4
-/* [RW 10] if Number of entries in usdmdp fifo will be higer than this
+/* [RW 10] if Number of entries in usdmdp fifo will be higher than this
    threshold then has_payload indication will be asserted; the default value
    should be equal to &gt;  write MBS size! */
 #define PXP2_REG_WR_USDMDP_TH                                   0x120348
 #define XSEM_XSEM_INT_MASK_0_REG_ADDRESS_ERROR_SIZE             0
 #define CFC_DEBUG1_REG_WRITE_AC                                 (0x1<<4)
 #define CFC_DEBUG1_REG_WRITE_AC_SIZE                            4
-/* [R 1] debug only: This bit indicates wheter indicates that external
+/* [R 1] debug only: This bit indicates whether indicates that external
    buffer was wrapped (oldest data was thrown); Relevant only when
    ~dbg_registers_debug_target=2 (PCI) & ~dbg_registers_full_mode=1 (wrap); */
 #define DBG_REG_WRAP_ON_EXT_BUFFER                              0xc124
 #define DBG_REG_WRAP_ON_EXT_BUFFER_SIZE                         1
-/* [R 1] debug only: This bit indicates wheter the internal buffer was
+/* [R 1] debug only: This bit indicates whether the internal buffer was
    wrapped (oldest data was thrown) Relevant only when
    ~dbg_registers_debug_target=0 (internal buffer) */
 #define DBG_REG_WRAP_ON_INT_BUFFER                              0xc128
 #define EMAC_RX_MODE_PROMISCUOUS                                (1L<<8)
 #define EMAC_RX_MTU_SIZE_JUMBO_ENA                              (1L<<31)
 #define EMAC_TX_MODE_EXT_PAUSE_EN                               (1L<<3)
+#define EMAC_TX_MODE_FLOW_EN                                    (1L<<4)
 #define MISC_REGISTERS_GPIO_0                                   0
 #define MISC_REGISTERS_GPIO_1                                   1
 #define MISC_REGISTERS_GPIO_2                                   2
 #define MISC_REGISTERS_GPIO_PORT_SHIFT                          4
 #define MISC_REGISTERS_GPIO_SET_POS                             8
 #define MISC_REGISTERS_RESET_REG_1_CLEAR                        0x588
+#define MISC_REGISTERS_RESET_REG_1_RST_NIG                      (0x1<<7)
 #define MISC_REGISTERS_RESET_REG_1_SET                          0x584
 #define MISC_REGISTERS_RESET_REG_2_CLEAR                        0x598
 #define MISC_REGISTERS_RESET_REG_2_RST_BMAC0                    (0x1<<0)
 #define HW_LOCK_MAX_RESOURCE_VALUE                              31
 #define HW_LOCK_RESOURCE_8072_MDIO                              0
 #define HW_LOCK_RESOURCE_GPIO                                   1
+#define HW_LOCK_RESOURCE_PORT0_ATT_MASK                         3
 #define HW_LOCK_RESOURCE_SPIO                                   2
+#define HW_LOCK_RESOURCE_UNDI                                   5
 #define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR                (1<<18)
 #define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT                (1<<31)
 #define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT                (1<<9)
 #define GRCBASE_MISC_AEU       GRCBASE_MISC
 
 
-/*the offset of the configuration space in the pci core register*/
+/* offset of configuration space in the pci core register */
 #define PCICFG_OFFSET                                  0x2000
 #define PCICFG_VENDOR_ID_OFFSET                        0x00
 #define PCICFG_DEVICE_ID_OFFSET                        0x02
 #define PCICFG_COMMAND_OFFSET                          0x04
+#define PCICFG_COMMAND_IO_SPACE                (1<<0)
+#define PCICFG_COMMAND_MEM_SPACE               (1<<1)
+#define PCICFG_COMMAND_BUS_MASTER              (1<<2)
+#define PCICFG_COMMAND_SPECIAL_CYCLES          (1<<3)
+#define PCICFG_COMMAND_MWI_CYCLES              (1<<4)
+#define PCICFG_COMMAND_VGA_SNOOP               (1<<5)
+#define PCICFG_COMMAND_PERR_ENA                (1<<6)
+#define PCICFG_COMMAND_STEPPING                (1<<7)
+#define PCICFG_COMMAND_SERR_ENA                (1<<8)
+#define PCICFG_COMMAND_FAST_B2B                (1<<9)
+#define PCICFG_COMMAND_INT_DISABLE             (1<<10)
+#define PCICFG_COMMAND_RESERVED                (0x1f<<11)
 #define PCICFG_STATUS_OFFSET                           0x06
-#define PCICFG_REVESION_ID                                 0x08
+#define PCICFG_REVESION_ID                             0x08
 #define PCICFG_CACHE_LINE_SIZE                         0x0c
 #define PCICFG_LATENCY_TIMER                           0x0d
-#define PCICFG_BAR_1_LOW                                   0x10
-#define PCICFG_BAR_1_HIGH                                  0x14
-#define PCICFG_BAR_2_LOW                                   0x18
-#define PCICFG_BAR_2_HIGH                                  0x1c
-#define PCICFG_SUBSYSTEM_VENDOR_ID_OFFSET      0x2c
+#define PCICFG_BAR_1_LOW                               0x10
+#define PCICFG_BAR_1_HIGH                              0x14
+#define PCICFG_BAR_2_LOW                               0x18
+#define PCICFG_BAR_2_HIGH                              0x1c
+#define PCICFG_SUBSYSTEM_VENDOR_ID_OFFSET              0x2c
 #define PCICFG_SUBSYSTEM_ID_OFFSET                     0x2e
-#define PCICFG_INT_LINE                                    0x3c
-#define PCICFG_INT_PIN                                     0x3d
-#define PCICFG_PM_CSR_OFFSET                   0x4c
-#define PCICFG_GRC_ADDRESS                                 0x78
-#define PCICFG_GRC_DATA                                    0x80
+#define PCICFG_INT_LINE                                0x3c
+#define PCICFG_INT_PIN                                 0x3d
+#define PCICFG_PM_CAPABILITY                           0x48
+#define PCICFG_PM_CAPABILITY_VERSION           (0x3<<16)
+#define PCICFG_PM_CAPABILITY_CLOCK             (1<<19)
+#define PCICFG_PM_CAPABILITY_RESERVED          (1<<20)
+#define PCICFG_PM_CAPABILITY_DSI               (1<<21)
+#define PCICFG_PM_CAPABILITY_AUX_CURRENT       (0x7<<22)
+#define PCICFG_PM_CAPABILITY_D1_SUPPORT        (1<<25)
+#define PCICFG_PM_CAPABILITY_D2_SUPPORT        (1<<26)
+#define PCICFG_PM_CAPABILITY_PME_IN_D0         (1<<27)
+#define PCICFG_PM_CAPABILITY_PME_IN_D1         (1<<28)
+#define PCICFG_PM_CAPABILITY_PME_IN_D2         (1<<29)
+#define PCICFG_PM_CAPABILITY_PME_IN_D3_HOT     (1<<30)
+#define PCICFG_PM_CAPABILITY_PME_IN_D3_COLD    (1<<31)
+#define PCICFG_PM_CSR_OFFSET                           0x4c
+#define PCICFG_PM_CSR_STATE                    (0x3<<0)
+#define PCICFG_PM_CSR_PME_ENABLE               (1<<8)
+#define PCICFG_PM_CSR_PME_STATUS               (1<<15)
+#define PCICFG_GRC_ADDRESS                             0x78
+#define PCICFG_GRC_DATA                                0x80
 #define PCICFG_DEVICE_CONTROL                          0xb4
 #define PCICFG_LINK_CONTROL                            0xbc
 
-#define PCICFG_COMMAND_IO_SPACE                    (1<<0)
-#define PCICFG_COMMAND_MEM_SPACE                   (1<<1)
-#define PCICFG_COMMAND_BUS_MASTER                  (1<<2)
-#define PCICFG_COMMAND_SPECIAL_CYCLES              (1<<3)
-#define PCICFG_COMMAND_MWI_CYCLES                  (1<<4)
-#define PCICFG_COMMAND_VGA_SNOOP                   (1<<5)
-#define PCICFG_COMMAND_PERR_ENA                    (1<<6)
-#define PCICFG_COMMAND_STEPPING                    (1<<7)
-#define PCICFG_COMMAND_SERR_ENA                    (1<<8)
-#define PCICFG_COMMAND_FAST_B2B                    (1<<9)
-#define PCICFG_COMMAND_INT_DISABLE                 (1<<10)
-#define PCICFG_COMMAND_RESERVED                    (0x1f<<11)
-
-#define PCICFG_PM_CSR_STATE                        (0x3<<0)
-#define PCICFG_PM_CSR_PME_STATUS                   (1<<15)
 
 #define BAR_USTRORM_INTMEM                             0x400000
 #define BAR_CSTRORM_INTMEM                             0x410000
 #define BAR_XSTRORM_INTMEM                             0x420000
 #define BAR_TSTRORM_INTMEM                             0x430000
 
+/* for accessing the IGU in case of status block ACK */
 #define BAR_IGU_INTMEM                                 0x440000
 
 #define BAR_DOORBELL_OFFSET                            0x800000
 
 #define BAR_ME_REGISTER                                0x450000
 
-
-#define GRC_CONFIG_2_SIZE_REG              0x408 /* config_2 offset */
-#define PCI_CONFIG_2_BAR1_SIZE                     (0xfL<<0)
+/* config_2 offset */
+#define GRC_CONFIG_2_SIZE_REG                          0x408
+#define PCI_CONFIG_2_BAR1_SIZE                 (0xfL<<0)
 #define PCI_CONFIG_2_BAR1_SIZE_DISABLED        (0L<<0)
 #define PCI_CONFIG_2_BAR1_SIZE_64K             (1L<<0)
 #define PCI_CONFIG_2_BAR1_SIZE_128K            (2L<<0)
 #define PCI_CONFIG_2_BAR1_SIZE_256M            (13L<<0)
 #define PCI_CONFIG_2_BAR1_SIZE_512M            (14L<<0)
 #define PCI_CONFIG_2_BAR1_SIZE_1G              (15L<<0)
-#define PCI_CONFIG_2_BAR1_64ENA                    (1L<<4)
-#define PCI_CONFIG_2_EXP_ROM_RETRY                 (1L<<5)
-#define PCI_CONFIG_2_CFG_CYCLE_RETRY               (1L<<6)
-#define PCI_CONFIG_2_FIRST_CFG_DONE                (1L<<7)
-#define PCI_CONFIG_2_EXP_ROM_SIZE                  (0xffL<<8)
+#define PCI_CONFIG_2_BAR1_64ENA                (1L<<4)
+#define PCI_CONFIG_2_EXP_ROM_RETRY             (1L<<5)
+#define PCI_CONFIG_2_CFG_CYCLE_RETRY           (1L<<6)
+#define PCI_CONFIG_2_FIRST_CFG_DONE            (1L<<7)
+#define PCI_CONFIG_2_EXP_ROM_SIZE              (0xffL<<8)
 #define PCI_CONFIG_2_EXP_ROM_SIZE_DISABLED     (0L<<8)
 #define PCI_CONFIG_2_EXP_ROM_SIZE_2K           (1L<<8)
 #define PCI_CONFIG_2_EXP_ROM_SIZE_4K           (2L<<8)
 #define PCI_CONFIG_2_EXP_ROM_SIZE_8M           (13L<<8)
 #define PCI_CONFIG_2_EXP_ROM_SIZE_16M          (14L<<8)
 #define PCI_CONFIG_2_EXP_ROM_SIZE_32M          (15L<<8)
-#define PCI_CONFIG_2_BAR_PREFETCH                  (1L<<16)
-#define PCI_CONFIG_2_RESERVED0                     (0x7fffL<<17)
+#define PCI_CONFIG_2_BAR_PREFETCH              (1L<<16)
+#define PCI_CONFIG_2_RESERVED0                 (0x7fffL<<17)
 
 /* config_3 offset */
-#define GRC_CONFIG_3_SIZE_REG                          (0x40c)
-#define PCI_CONFIG_3_STICKY_BYTE                   (0xffL<<0)
-#define PCI_CONFIG_3_FORCE_PME                     (1L<<24)
-#define PCI_CONFIG_3_PME_STATUS                    (1L<<25)
-#define PCI_CONFIG_3_PME_ENABLE                    (1L<<26)
-#define PCI_CONFIG_3_PM_STATE                      (0x3L<<27)
-#define PCI_CONFIG_3_VAUX_PRESET                   (1L<<30)
-#define PCI_CONFIG_3_PCI_POWER                     (1L<<31)
-
-/* config_2 offset */
-#define GRC_CONFIG_2_SIZE_REG              0x408
+#define GRC_CONFIG_3_SIZE_REG                          0x40c
+#define PCI_CONFIG_3_STICKY_BYTE               (0xffL<<0)
+#define PCI_CONFIG_3_FORCE_PME                 (1L<<24)
+#define PCI_CONFIG_3_PME_STATUS                (1L<<25)
+#define PCI_CONFIG_3_PME_ENABLE                (1L<<26)
+#define PCI_CONFIG_3_PM_STATE                  (0x3L<<27)
+#define PCI_CONFIG_3_VAUX_PRESET               (1L<<30)
+#define PCI_CONFIG_3_PCI_POWER                 (1L<<31)
 
 #define GRC_BAR2_CONFIG                                0x4e0
-#define PCI_CONFIG_2_BAR2_SIZE                     (0xfL<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_DISABLED            (0L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_64K                 (1L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_128K                (2L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_256K                (3L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_512K                (4L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_1M                  (5L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_2M                  (6L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_4M                  (7L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_8M                  (8L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_16M                 (9L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_32M                 (10L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_64M                 (11L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_128M                (12L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_256M                (13L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_512M                (14L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_1G                  (15L<<0)
-#define PCI_CONFIG_2_BAR2_64ENA                    (1L<<4)
+#define PCI_CONFIG_2_BAR2_SIZE                 (0xfL<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_DISABLED        (0L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_64K             (1L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_128K            (2L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_256K            (3L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_512K            (4L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_1M              (5L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_2M              (6L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_4M              (7L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_8M              (8L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_16M             (9L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_32M             (10L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_64M             (11L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_128M            (12L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_256M            (13L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_512M            (14L<<0)
+#define PCI_CONFIG_2_BAR2_SIZE_1G              (15L<<0)
+#define PCI_CONFIG_2_BAR2_64ENA                (1L<<4)
+
+#define PCI_PM_DATA_A                                  0x410
+#define PCI_PM_DATA_B                                  0x414
+#define PCI_ID_VAL1                                    0x434
+#define PCI_ID_VAL2                                    0x438
 
-#define PCI_PM_DATA_A                                  (0x410)
-#define PCI_PM_DATA_B                                  (0x414)
-#define PCI_ID_VAL1                                    (0x434)
-#define PCI_ID_VAL2                                    (0x438)
 
 #define MDIO_REG_BANK_CL73_IEEEB0                      0x0
 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL               0x0
@@ -5522,6 +5560,8 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_PMA_REG_GEN_CTRL          0xca10
 #define MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP    0x0188
 #define MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET          0x018a
+#define MDIO_PMA_REG_M8051_MSGIN_REG   0xca12
+#define MDIO_PMA_REG_M8051_MSGOUT_REG  0xca13
 #define MDIO_PMA_REG_ROM_VER1          0xca19
 #define MDIO_PMA_REG_ROM_VER2          0xca1a
 #define MDIO_PMA_REG_EDC_FFE_MAIN      0xca1b
@@ -5576,7 +5616,8 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_AN_REG_LINK_STATUS        0x8304
 #define MDIO_AN_REG_CL37_CL73          0x8370
 #define MDIO_AN_REG_CL37_AN            0xffe0
-#define MDIO_AN_REG_CL37_FD            0xffe4
+#define MDIO_AN_REG_CL37_FC_LD         0xffe4
+#define MDIO_AN_REG_CL37_FC_LP         0xffe5
 
 
 #define IGU_FUNC_BASE                  0x0400
@@ -5600,4 +5641,13 @@ Theotherbitsarereservedandshouldbezero*/
 #define IGU_INT_NOP                            2
 #define IGU_INT_NOP2                   3
 
+#define COMMAND_REG_INT_ACK        0x0
+#define COMMAND_REG_PROD_UPD       0x4
+#define COMMAND_REG_ATTN_BITS_UPD   0x8
+#define COMMAND_REG_ATTN_BITS_SET   0xc
+#define COMMAND_REG_ATTN_BITS_CLR   0x10
+#define COMMAND_REG_COALESCE_NOW    0x14
+#define COMMAND_REG_SIMD_MASK      0x18
+#define COMMAND_REG_SIMD_NOMASK     0x1c
+
 
index 7d63f8ced24b12568fc49ebfa06fd588e49b6fc9..4b47f4ece5b70904c9ef68c06f468489ec70939a 100644 (file)
@@ -26,6 +26,8 @@ obj-$(CONFIG_HT_IRQ) += htirq.o
 # Build Intel IOMMU support
 obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
 
+obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
+
 #
 # Some architectures use the generic PCI setup functions
 #
diff --git a/drivers/pci/dma_remapping.h b/drivers/pci/dma_remapping.h
new file mode 100644 (file)
index 0000000..bff5c65
--- /dev/null
@@ -0,0 +1,157 @@
+#ifndef _DMA_REMAPPING_H
+#define _DMA_REMAPPING_H
+
+/*
+ * We need a fixed PAGE_SIZE of 4K irrespective of
+ * arch PAGE_SIZE for IOMMU page tables.
+ */
+#define PAGE_SHIFT_4K          (12)
+#define PAGE_SIZE_4K           (1UL << PAGE_SHIFT_4K)
+#define PAGE_MASK_4K           (((u64)-1) << PAGE_SHIFT_4K)
+#define PAGE_ALIGN_4K(addr)    (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
+
+#define IOVA_PFN(addr)         ((addr) >> PAGE_SHIFT_4K)
+#define DMA_32BIT_PFN          IOVA_PFN(DMA_32BIT_MASK)
+#define DMA_64BIT_PFN          IOVA_PFN(DMA_64BIT_MASK)
+
+
+/*
+ * 0: Present
+ * 1-11: Reserved
+ * 12-63: Context Ptr (12 - (haw-1))
+ * 64-127: Reserved
+ */
+struct root_entry {
+       u64     val;
+       u64     rsvd1;
+};
+#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry))
+static inline bool root_present(struct root_entry *root)
+{
+       return (root->val & 1);
+}
+static inline void set_root_present(struct root_entry *root)
+{
+       root->val |= 1;
+}
+static inline void set_root_value(struct root_entry *root, unsigned long value)
+{
+       root->val |= value & PAGE_MASK_4K;
+}
+
+struct context_entry;
+static inline struct context_entry *
+get_context_addr_from_root(struct root_entry *root)
+{
+       return (struct context_entry *)
+               (root_present(root)?phys_to_virt(
+               root->val & PAGE_MASK_4K):
+               NULL);
+}
+
+/*
+ * low 64 bits:
+ * 0: present
+ * 1: fault processing disable
+ * 2-3: translation type
+ * 12-63: address space root
+ * high 64 bits:
+ * 0-2: address width
+ * 3-6: aval
+ * 8-23: domain id
+ */
+struct context_entry {
+       u64 lo;
+       u64 hi;
+};
+#define context_present(c) ((c).lo & 1)
+#define context_fault_disable(c) (((c).lo >> 1) & 1)
+#define context_translation_type(c) (((c).lo >> 2) & 3)
+#define context_address_root(c) ((c).lo & PAGE_MASK_4K)
+#define context_address_width(c) ((c).hi &  7)
+#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1))
+
+#define context_set_present(c) do {(c).lo |= 1;} while (0)
+#define context_set_fault_enable(c) \
+       do {(c).lo &= (((u64)-1) << 2) | 1;} while (0)
+#define context_set_translation_type(c, val) \
+       do { \
+               (c).lo &= (((u64)-1) << 4) | 3; \
+               (c).lo |= ((val) & 3) << 2; \
+       } while (0)
+#define CONTEXT_TT_MULTI_LEVEL 0
+#define context_set_address_root(c, val) \
+       do {(c).lo |= (val) & PAGE_MASK_4K;} while (0)
+#define context_set_address_width(c, val) do {(c).hi |= (val) & 7;} while (0)
+#define context_set_domain_id(c, val) \
+       do {(c).hi |= ((val) & ((1 << 16) - 1)) << 8;} while (0)
+#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while (0)
+
+/*
+ * 0: readable
+ * 1: writable
+ * 2-6: reserved
+ * 7: super page
+ * 8-11: available
+ * 12-63: Host physcial address
+ */
+struct dma_pte {
+       u64 val;
+};
+#define dma_clear_pte(p)       do {(p).val = 0;} while (0)
+
+#define DMA_PTE_READ (1)
+#define DMA_PTE_WRITE (2)
+
+#define dma_set_pte_readable(p) do {(p).val |= DMA_PTE_READ;} while (0)
+#define dma_set_pte_writable(p) do {(p).val |= DMA_PTE_WRITE;} while (0)
+#define dma_set_pte_prot(p, prot) \
+               do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0)
+#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
+#define dma_set_pte_addr(p, addr) do {\
+               (p).val |= ((addr) & PAGE_MASK_4K); } while (0)
+#define dma_pte_present(p) (((p).val & 3) != 0)
+
+struct intel_iommu;
+
+struct dmar_domain {
+       int     id;                     /* domain id */
+       struct intel_iommu *iommu;      /* back pointer to owning iommu */
+
+       struct list_head devices;       /* all devices' list */
+       struct iova_domain iovad;       /* iova's that belong to this domain */
+
+       struct dma_pte  *pgd;           /* virtual address */
+       spinlock_t      mapping_lock;   /* page table lock */
+       int             gaw;            /* max guest address width */
+
+       /* adjusted guest address width, 0 is level 2 30-bit */
+       int             agaw;
+
+#define DOMAIN_FLAG_MULTIPLE_DEVICES 1
+       int             flags;
+};
+
+/* PCI domain-device relationship */
+struct device_domain_info {
+       struct list_head link;  /* link to domain siblings */
+       struct list_head global; /* link to global list */
+       u8 bus;                 /* PCI bus numer */
+       u8 devfn;               /* PCI devfn number */
+       struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */
+       struct dmar_domain *domain; /* pointer to domain */
+};
+
+extern int init_dmars(void);
+extern void free_dmar_iommu(struct intel_iommu *iommu);
+
+extern int dmar_disabled;
+
+#ifndef CONFIG_DMAR_GFX_WA
+static inline void iommu_prepare_gfx_mapping(void)
+{
+       return;
+}
+#endif /* !CONFIG_DMAR_GFX_WA */
+
+#endif
index 8bf86ae2333fc963207d2b14d2702c96a9532bc6..bd2c01674f5ec1cd07063ce499e38e5faf805995 100644 (file)
  * Author: Shaohua Li <shaohua.li@intel.com>
  * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
  *
- * This file implements early detection/parsing of DMA Remapping Devices
+ * This file implements early detection/parsing of Remapping Devices
  * reported to OS through BIOS via DMA remapping reporting (DMAR) ACPI
  * tables.
+ *
+ * These routines are used by both DMA-remapping and Interrupt-remapping
  */
 
 #include <linux/pci.h>
 #include <linux/dmar.h>
+#include <linux/timer.h>
 #include "iova.h"
 #include "intel-iommu.h"
 
@@ -37,7 +40,6 @@
  * these units are not supported by the architecture.
  */
 LIST_HEAD(dmar_drhd_units);
-LIST_HEAD(dmar_rmrr_units);
 
 static struct acpi_table_header * __initdata dmar_tbl;
 
@@ -53,11 +55,6 @@ static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
                list_add(&drhd->list, &dmar_drhd_units);
 }
 
-static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
-{
-       list_add(&rmrr->list, &dmar_rmrr_units);
-}
-
 static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
                                           struct pci_dev **dev, u16 segment)
 {
@@ -172,19 +169,37 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
        struct acpi_dmar_hardware_unit *drhd;
        struct dmar_drhd_unit *dmaru;
        int ret = 0;
-       static int include_all;
 
        dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
        if (!dmaru)
                return -ENOMEM;
 
+       dmaru->hdr = header;
        drhd = (struct acpi_dmar_hardware_unit *)header;
        dmaru->reg_base_addr = drhd->address;
        dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
 
+       ret = alloc_iommu(dmaru);
+       if (ret) {
+               kfree(dmaru);
+               return ret;
+       }
+       dmar_register_drhd_unit(dmaru);
+       return 0;
+}
+
+static int __init
+dmar_parse_dev(struct dmar_drhd_unit *dmaru)
+{
+       struct acpi_dmar_hardware_unit *drhd;
+       static int include_all;
+       int ret;
+
+       drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
+
        if (!dmaru->include_all)
                ret = dmar_parse_dev_scope((void *)(drhd + 1),
-                               ((void *)drhd) + header->length,
+                               ((void *)drhd) + drhd->header.length,
                                &dmaru->devices_cnt, &dmaru->devices,
                                drhd->segment);
        else {
@@ -197,37 +212,59 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
                include_all = 1;
        }
 
-       if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all))
+       if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) {
+               list_del(&dmaru->list);
                kfree(dmaru);
-       else
-               dmar_register_drhd_unit(dmaru);
+       }
        return ret;
 }
 
+#ifdef CONFIG_DMAR
+LIST_HEAD(dmar_rmrr_units);
+
+static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
+{
+       list_add(&rmrr->list, &dmar_rmrr_units);
+}
+
+
 static int __init
 dmar_parse_one_rmrr(struct acpi_dmar_header *header)
 {
        struct acpi_dmar_reserved_memory *rmrr;
        struct dmar_rmrr_unit *rmrru;
-       int ret = 0;
 
        rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
        if (!rmrru)
                return -ENOMEM;
 
+       rmrru->hdr = header;
        rmrr = (struct acpi_dmar_reserved_memory *)header;
        rmrru->base_address = rmrr->base_address;
        rmrru->end_address = rmrr->end_address;
+
+       dmar_register_rmrr_unit(rmrru);
+       return 0;
+}
+
+static int __init
+rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
+{
+       struct acpi_dmar_reserved_memory *rmrr;
+       int ret;
+
+       rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
        ret = dmar_parse_dev_scope((void *)(rmrr + 1),
-               ((void *)rmrr) + header->length,
+               ((void *)rmrr) + rmrr->header.length,
                &rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
 
-       if (ret || (rmrru->devices_cnt == 0))
+       if (ret || (rmrru->devices_cnt == 0)) {
+               list_del(&rmrru->list);
                kfree(rmrru);
-       else
-               dmar_register_rmrr_unit(rmrru);
+       }
        return ret;
 }
+#endif
 
 static void __init
 dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
@@ -252,6 +289,7 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
        }
 }
 
+
 /**
  * parse_dmar_table - parses the DMA reporting table
  */
@@ -284,7 +322,9 @@ parse_dmar_table(void)
                        ret = dmar_parse_one_drhd(entry_header);
                        break;
                case ACPI_DMAR_TYPE_RESERVED_MEMORY:
+#ifdef CONFIG_DMAR
                        ret = dmar_parse_one_rmrr(entry_header);
+#endif
                        break;
                default:
                        printk(KERN_WARNING PREFIX
@@ -300,15 +340,77 @@ parse_dmar_table(void)
        return ret;
 }
 
+int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
+                         struct pci_dev *dev)
+{
+       int index;
+
+       while (dev) {
+               for (index = 0; index < cnt; index++)
+                       if (dev == devices[index])
+                               return 1;
 
-int __init dmar_table_init(void)
+               /* Check our parent */
+               dev = dev->bus->self;
+       }
+
+       return 0;
+}
+
+struct dmar_drhd_unit *
+dmar_find_matched_drhd_unit(struct pci_dev *dev)
 {
+       struct dmar_drhd_unit *drhd = NULL;
+
+       list_for_each_entry(drhd, &dmar_drhd_units, list) {
+               if (drhd->include_all || dmar_pci_device_match(drhd->devices,
+                                               drhd->devices_cnt, dev))
+                       return drhd;
+       }
+
+       return NULL;
+}
+
+int __init dmar_dev_scope_init(void)
+{
+       struct dmar_drhd_unit *drhd;
+       int ret = -ENODEV;
+
+       for_each_drhd_unit(drhd) {
+               ret = dmar_parse_dev(drhd);
+               if (ret)
+                       return ret;
+       }
+
+#ifdef CONFIG_DMAR
+       {
+               struct dmar_rmrr_unit *rmrr;
+               for_each_rmrr_units(rmrr) {
+                       ret = rmrr_parse_dev(rmrr);
+                       if (ret)
+                               return ret;
+               }
+       }
+#endif
+
+       return ret;
+}
 
+
+int __init dmar_table_init(void)
+{
+       static int dmar_table_initialized;
        int ret;
 
+       if (dmar_table_initialized)
+               return 0;
+
+       dmar_table_initialized = 1;
+
        ret = parse_dmar_table();
        if (ret) {
-               printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
+               if (ret != -ENODEV)
+                       printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
                return ret;
        }
 
@@ -317,9 +419,14 @@ int __init dmar_table_init(void)
                return -ENODEV;
        }
 
+#ifdef CONFIG_DMAR
        if (list_empty(&dmar_rmrr_units))
                printk(KERN_INFO PREFIX "No RMRR found\n");
+#endif
 
+#ifdef CONFIG_INTR_REMAP
+       parse_ioapics_under_ir();
+#endif
        return 0;
 }
 
@@ -341,3 +448,255 @@ int __init early_dmar_detect(void)
 
        return (ACPI_SUCCESS(status) ? 1 : 0);
 }
+
+void __init detect_intel_iommu(void)
+{
+       int ret;
+
+       ret = early_dmar_detect();
+
+#ifdef CONFIG_DMAR
+       {
+               struct acpi_table_dmar *dmar;
+               /*
+                * for now we will disable dma-remapping when interrupt
+                * remapping is enabled.
+                * When support for queued invalidation for IOTLB invalidation
+                * is added, we will not need this any more.
+                */
+               dmar = (struct acpi_table_dmar *) dmar_tbl;
+               if (ret && cpu_has_x2apic && dmar->flags & 0x1) {
+                       printk(KERN_INFO
+                              "Queued invalidation will be enabled to support "
+                              "x2apic and Intr-remapping.\n");
+                       printk(KERN_INFO
+                              "Disabling IOMMU detection, because of missing "
+                              "queued invalidation support for IOTLB "
+                              "invalidation\n");
+                       printk(KERN_INFO
+                              "Use \"nox2apic\", if you want to use Intel "
+                              " IOMMU for DMA-remapping and don't care about "
+                              " x2apic support\n");
+
+                       dmar_disabled = 1;
+                       return;
+               }
+
+               if (ret && !no_iommu && !iommu_detected && !swiotlb &&
+                   !dmar_disabled)
+                       iommu_detected = 1;
+       }
+#endif
+}
+
+
+int alloc_iommu(struct dmar_drhd_unit *drhd)
+{
+       struct intel_iommu *iommu;
+       int map_size;
+       u32 ver;
+       static int iommu_allocated = 0;
+
+       iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+       if (!iommu)
+               return -ENOMEM;
+
+       iommu->seq_id = iommu_allocated++;
+
+       iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K);
+       if (!iommu->reg) {
+               printk(KERN_ERR "IOMMU: can't map the region\n");
+               goto error;
+       }
+       iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
+       iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
+
+       /* the registers might be more than one page */
+       map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
+               cap_max_fault_reg_offset(iommu->cap));
+       map_size = PAGE_ALIGN_4K(map_size);
+       if (map_size > PAGE_SIZE_4K) {
+               iounmap(iommu->reg);
+               iommu->reg = ioremap(drhd->reg_base_addr, map_size);
+               if (!iommu->reg) {
+                       printk(KERN_ERR "IOMMU: can't map the region\n");
+                       goto error;
+               }
+       }
+
+       ver = readl(iommu->reg + DMAR_VER_REG);
+       pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
+               drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
+               iommu->cap, iommu->ecap);
+
+       spin_lock_init(&iommu->register_lock);
+
+       drhd->iommu = iommu;
+       return 0;
+error:
+       kfree(iommu);
+       return -1;
+}
+
+void free_iommu(struct intel_iommu *iommu)
+{
+       if (!iommu)
+               return;
+
+#ifdef CONFIG_DMAR
+       free_dmar_iommu(iommu);
+#endif
+
+       if (iommu->reg)
+               iounmap(iommu->reg);
+       kfree(iommu);
+}
+
+/*
+ * Reclaim all the submitted descriptors which have completed its work.
+ */
+static inline void reclaim_free_desc(struct q_inval *qi)
+{
+       while (qi->desc_status[qi->free_tail] == QI_DONE) {
+               qi->desc_status[qi->free_tail] = QI_FREE;
+               qi->free_tail = (qi->free_tail + 1) % QI_LENGTH;
+               qi->free_cnt++;
+       }
+}
+
+/*
+ * Submit the queued invalidation descriptor to the remapping
+ * hardware unit and wait for its completion.
+ */
+void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
+{
+       struct q_inval *qi = iommu->qi;
+       struct qi_desc *hw, wait_desc;
+       int wait_index, index;
+       unsigned long flags;
+
+       if (!qi)
+               return;
+
+       hw = qi->desc;
+
+       spin_lock(&qi->q_lock);
+       while (qi->free_cnt < 3) {
+               spin_unlock(&qi->q_lock);
+               cpu_relax();
+               spin_lock(&qi->q_lock);
+       }
+
+       index = qi->free_head;
+       wait_index = (index + 1) % QI_LENGTH;
+
+       qi->desc_status[index] = qi->desc_status[wait_index] = QI_IN_USE;
+
+       hw[index] = *desc;
+
+       wait_desc.low = QI_IWD_STATUS_DATA(2) | QI_IWD_STATUS_WRITE | QI_IWD_TYPE;
+       wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]);
+
+       hw[wait_index] = wait_desc;
+
+       __iommu_flush_cache(iommu, &hw[index], sizeof(struct qi_desc));
+       __iommu_flush_cache(iommu, &hw[wait_index], sizeof(struct qi_desc));
+
+       qi->free_head = (qi->free_head + 2) % QI_LENGTH;
+       qi->free_cnt -= 2;
+
+       spin_lock_irqsave(&iommu->register_lock, flags);
+       /*
+        * update the HW tail register indicating the presence of
+        * new descriptors.
+        */
+       writel(qi->free_head << 4, iommu->reg + DMAR_IQT_REG);
+       spin_unlock_irqrestore(&iommu->register_lock, flags);
+
+       while (qi->desc_status[wait_index] != QI_DONE) {
+               spin_unlock(&qi->q_lock);
+               cpu_relax();
+               spin_lock(&qi->q_lock);
+       }
+
+       qi->desc_status[index] = QI_DONE;
+
+       reclaim_free_desc(qi);
+       spin_unlock(&qi->q_lock);
+}
+
+/*
+ * Flush the global interrupt entry cache.
+ */
+void qi_global_iec(struct intel_iommu *iommu)
+{
+       struct qi_desc desc;
+
+       desc.low = QI_IEC_TYPE;
+       desc.high = 0;
+
+       qi_submit_sync(&desc, iommu);
+}
+
+/*
+ * Enable Queued Invalidation interface. This is a must to support
+ * interrupt-remapping. Also used by DMA-remapping, which replaces
+ * register based IOTLB invalidation.
+ */
+int dmar_enable_qi(struct intel_iommu *iommu)
+{
+       u32 cmd, sts;
+       unsigned long flags;
+       struct q_inval *qi;
+
+       if (!ecap_qis(iommu->ecap))
+               return -ENOENT;
+
+       /*
+        * queued invalidation is already setup and enabled.
+        */
+       if (iommu->qi)
+               return 0;
+
+       iommu->qi = kmalloc(sizeof(*qi), GFP_KERNEL);
+       if (!iommu->qi)
+               return -ENOMEM;
+
+       qi = iommu->qi;
+
+       qi->desc = (void *)(get_zeroed_page(GFP_KERNEL));
+       if (!qi->desc) {
+               kfree(qi);
+               iommu->qi = 0;
+               return -ENOMEM;
+       }
+
+       qi->desc_status = kmalloc(QI_LENGTH * sizeof(int), GFP_KERNEL);
+       if (!qi->desc_status) {
+               free_page((unsigned long) qi->desc);
+               kfree(qi);
+               iommu->qi = 0;
+               return -ENOMEM;
+       }
+
+       qi->free_head = qi->free_tail = 0;
+       qi->free_cnt = QI_LENGTH;
+
+       spin_lock_init(&qi->q_lock);
+
+       spin_lock_irqsave(&iommu->register_lock, flags);
+       /* write zero to the tail reg */
+       writel(0, iommu->reg + DMAR_IQT_REG);
+
+       dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc));
+
+       cmd = iommu->gcmd | DMA_GCMD_QIE;
+       iommu->gcmd |= DMA_GCMD_QIE;
+       writel(cmd, iommu->reg + DMAR_GCMD_REG);
+
+       /* Make sure hardware complete it */
+       IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
+       spin_unlock_irqrestore(&iommu->register_lock, flags);
+
+       return 0;
+}
index 8d0e60ac849cb5f34e609fdaf9215688091728a7..389fdd6f4a9f6afcdd0877150887dc1f1571a914 100644 (file)
@@ -49,8 +49,6 @@
 
 #define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
 
-#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) /* 10sec */
-
 #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1)
 
 
@@ -58,8 +56,6 @@ static void flush_unmaps_timeout(unsigned long data);
 
 DEFINE_TIMER(unmap_timer,  flush_unmaps_timeout, 0, 0);
 
-static struct intel_iommu *g_iommus;
-
 #define HIGH_WATER_MARK 250
 struct deferred_flush_tables {
        int next;
@@ -80,7 +76,7 @@ static long list_size;
 
 static void domain_remove_dev_info(struct dmar_domain *domain);
 
-static int dmar_disabled;
+int dmar_disabled;
 static int __initdata dmar_map_gfx = 1;
 static int dmar_forcedac;
 static int intel_iommu_strict;
@@ -185,13 +181,6 @@ void free_iova_mem(struct iova *iova)
        kmem_cache_free(iommu_iova_cache, iova);
 }
 
-static inline void __iommu_flush_cache(
-       struct intel_iommu *iommu, void *addr, int size)
-{
-       if (!ecap_coherent(iommu->ecap))
-               clflush_cache_range(addr, size);
-}
-
 /* Gets context entry for a given bus and devfn */
 static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
                u8 bus, u8 devfn)
@@ -488,19 +477,6 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu)
        return 0;
 }
 
-#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \
-{\
-       cycles_t start_time = get_cycles();\
-       while (1) {\
-               sts = op (iommu->reg + offset);\
-               if (cond)\
-                       break;\
-               if (DMAR_OPERATION_TIMEOUT < (get_cycles() - start_time))\
-                       panic("DMAR hardware is malfunctioning\n");\
-               cpu_relax();\
-       }\
-}
-
 static void iommu_set_root_entry(struct intel_iommu *iommu)
 {
        void *addr;
@@ -990,6 +966,8 @@ static int iommu_init_domains(struct intel_iommu *iommu)
                return -ENOMEM;
        }
 
+       spin_lock_init(&iommu->lock);
+
        /*
         * if Caching mode is set, then invalid translations are tagged
         * with domainid 0. Hence we need to pre-allocate it.
@@ -998,62 +976,15 @@ static int iommu_init_domains(struct intel_iommu *iommu)
                set_bit(0, iommu->domain_ids);
        return 0;
 }
-static struct intel_iommu *alloc_iommu(struct intel_iommu *iommu,
-                                       struct dmar_drhd_unit *drhd)
-{
-       int ret;
-       int map_size;
-       u32 ver;
-
-       iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K);
-       if (!iommu->reg) {
-               printk(KERN_ERR "IOMMU: can't map the region\n");
-               goto error;
-       }
-       iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
-       iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
-
-       /* the registers might be more than one page */
-       map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
-               cap_max_fault_reg_offset(iommu->cap));
-       map_size = PAGE_ALIGN_4K(map_size);
-       if (map_size > PAGE_SIZE_4K) {
-               iounmap(iommu->reg);
-               iommu->reg = ioremap(drhd->reg_base_addr, map_size);
-               if (!iommu->reg) {
-                       printk(KERN_ERR "IOMMU: can't map the region\n");
-                       goto error;
-               }
-       }
-
-       ver = readl(iommu->reg + DMAR_VER_REG);
-       pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
-               drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
-               iommu->cap, iommu->ecap);
-       ret = iommu_init_domains(iommu);
-       if (ret)
-               goto error_unmap;
-       spin_lock_init(&iommu->lock);
-       spin_lock_init(&iommu->register_lock);
 
-       drhd->iommu = iommu;
-       return iommu;
-error_unmap:
-       iounmap(iommu->reg);
-error:
-       kfree(iommu);
-       return NULL;
-}
 
 static void domain_exit(struct dmar_domain *domain);
-static void free_iommu(struct intel_iommu *iommu)
+
+void free_dmar_iommu(struct intel_iommu *iommu)
 {
        struct dmar_domain *domain;
        int i;
 
-       if (!iommu)
-               return;
-
        i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap));
        for (; i < cap_ndoms(iommu->cap); ) {
                domain = iommu->domains[i];
@@ -1078,10 +1009,6 @@ static void free_iommu(struct intel_iommu *iommu)
 
        /* free context mapping */
        free_context_table(iommu);
-
-       if (iommu->reg)
-               iounmap(iommu->reg);
-       kfree(iommu);
 }
 
 static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
@@ -1426,37 +1353,6 @@ find_domain(struct pci_dev *pdev)
        return NULL;
 }
 
-static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
-     struct pci_dev *dev)
-{
-       int index;
-
-       while (dev) {
-               for (index = 0; index < cnt; index++)
-                       if (dev == devices[index])
-                               return 1;
-
-               /* Check our parent */
-               dev = dev->bus->self;
-       }
-
-       return 0;
-}
-
-static struct dmar_drhd_unit *
-dmar_find_matched_drhd_unit(struct pci_dev *dev)
-{
-       struct dmar_drhd_unit *drhd = NULL;
-
-       list_for_each_entry(drhd, &dmar_drhd_units, list) {
-               if (drhd->include_all || dmar_pci_device_match(drhd->devices,
-                                               drhd->devices_cnt, dev))
-                       return drhd;
-       }
-
-       return NULL;
-}
-
 /* domain is initialized */
 static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 {
@@ -1729,8 +1625,6 @@ int __init init_dmars(void)
         * endfor
         */
        for_each_drhd_unit(drhd) {
-               if (drhd->ignored)
-                       continue;
                g_num_of_iommus++;
                /*
                 * lock not needed as this is only incremented in the single
@@ -1739,12 +1633,6 @@ int __init init_dmars(void)
                 */
        }
 
-       g_iommus = kzalloc(g_num_of_iommus * sizeof(*iommu), GFP_KERNEL);
-       if (!g_iommus) {
-               ret = -ENOMEM;
-               goto error;
-       }
-
        deferred_flush = kzalloc(g_num_of_iommus *
                sizeof(struct deferred_flush_tables), GFP_KERNEL);
        if (!deferred_flush) {
@@ -1752,16 +1640,15 @@ int __init init_dmars(void)
                goto error;
        }
 
-       i = 0;
        for_each_drhd_unit(drhd) {
                if (drhd->ignored)
                        continue;
-               iommu = alloc_iommu(&g_iommus[i], drhd);
-               i++;
-               if (!iommu) {
-                       ret = -ENOMEM;
+
+               iommu = drhd->iommu;
+
+               ret = iommu_init_domains(iommu);
+               if (ret)
                        goto error;
-               }
 
                /*
                 * TBD:
@@ -1845,7 +1732,6 @@ error:
                iommu = drhd->iommu;
                free_iommu(iommu);
        }
-       kfree(g_iommus);
        return ret;
 }
 
@@ -2002,7 +1888,10 @@ static void flush_unmaps(void)
        /* just flush them all */
        for (i = 0; i < g_num_of_iommus; i++) {
                if (deferred_flush[i].next) {
-                       iommu_flush_iotlb_global(&g_iommus[i], 0);
+                       struct intel_iommu *iommu =
+                               deferred_flush[i].domain[0]->iommu;
+
+                       iommu_flush_iotlb_global(iommu, 0);
                        for (j = 0; j < deferred_flush[i].next; j++) {
                                __free_iova(&deferred_flush[i].domain[j]->iovad,
                                                deferred_flush[i].iova[j]);
@@ -2032,7 +1921,8 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova)
        if (list_size == HIGH_WATER_MARK)
                flush_unmaps();
 
-       iommu_id = dom->iommu - g_iommus;
+       iommu_id = dom->iommu->seq_id;
+
        next = deferred_flush[iommu_id].next;
        deferred_flush[iommu_id].domain[next] = dom;
        deferred_flush[iommu_id].iova[next] = iova;
@@ -2348,15 +2238,6 @@ static void __init iommu_exit_mempool(void)
 
 }
 
-void __init detect_intel_iommu(void)
-{
-       if (swiotlb || no_iommu || iommu_detected || dmar_disabled)
-               return;
-       if (early_dmar_detect()) {
-               iommu_detected = 1;
-       }
-}
-
 static void __init init_no_remapping_devices(void)
 {
        struct dmar_drhd_unit *drhd;
@@ -2403,12 +2284,19 @@ int __init intel_iommu_init(void)
 {
        int ret = 0;
 
-       if (no_iommu || swiotlb || dmar_disabled)
-               return -ENODEV;
-
        if (dmar_table_init())
                return  -ENODEV;
 
+       if (dmar_dev_scope_init())
+               return  -ENODEV;
+
+       /*
+        * Check the need for DMA-remapping initialization now.
+        * Above initialization will also be used by Interrupt-remapping.
+        */
+       if (no_iommu || swiotlb || dmar_disabled)
+               return -ENODEV;
+
        iommu_init_mempool();
        dmar_init_reserved_ranges();
 
index afc0ad96122e85ffc52d9570c497de7e304b37db..2142c01e0143c947e353e8ce26b29eff090f3d7b 100644 (file)
 #include <linux/sysdev.h>
 #include "iova.h"
 #include <linux/io.h>
-
-/*
- * We need a fixed PAGE_SIZE of 4K irrespective of
- * arch PAGE_SIZE for IOMMU page tables.
- */
-#define PAGE_SHIFT_4K          (12)
-#define PAGE_SIZE_4K           (1UL << PAGE_SHIFT_4K)
-#define PAGE_MASK_4K           (((u64)-1) << PAGE_SHIFT_4K)
-#define PAGE_ALIGN_4K(addr)    (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
-
-#define IOVA_PFN(addr)         ((addr) >> PAGE_SHIFT_4K)
-#define DMA_32BIT_PFN          IOVA_PFN(DMA_32BIT_MASK)
-#define DMA_64BIT_PFN          IOVA_PFN(DMA_64BIT_MASK)
+#include <asm/cacheflush.h>
+#include "dma_remapping.h"
 
 /*
  * Intel IOMMU register specification per version 1.0 public spec.
 #define        DMAR_PLMLIMIT_REG 0x6c  /* PMRR low limit */
 #define        DMAR_PHMBASE_REG 0x70   /* pmrr high base addr */
 #define        DMAR_PHMLIMIT_REG 0x78  /* pmrr high limit */
+#define DMAR_IQH_REG   0x80    /* Invalidation queue head register */
+#define DMAR_IQT_REG   0x88    /* Invalidation queue tail register */
+#define DMAR_IQA_REG   0x90    /* Invalidation queue addr register */
+#define DMAR_ICS_REG   0x98    /* Invalidation complete status register */
+#define DMAR_IRTA_REG  0xb8    /* Interrupt remapping table addr register */
 
 #define OFFSET_STRIDE          (9)
 /*
@@ -126,6 +120,10 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
 #define ecap_max_iotlb_offset(e) \
        (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16)
 #define ecap_coherent(e)       ((e) & 0x1)
+#define ecap_qis(e)            ((e) & 0x2)
+#define ecap_eim_support(e)    ((e >> 4) & 0x1)
+#define ecap_ir_support(e)     ((e >> 3) & 0x1)
+#define ecap_max_handle_mask(e) ((e >> 20) & 0xf)
 
 
 /* IOTLB_REG */
@@ -141,6 +139,17 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
 #define DMA_TLB_IH_NONLEAF (((u64)1) << 6)
 #define DMA_TLB_MAX_SIZE (0x3f)
 
+/* INVALID_DESC */
+#define DMA_ID_TLB_GLOBAL_FLUSH        (((u64)1) << 3)
+#define DMA_ID_TLB_DSI_FLUSH   (((u64)2) << 3)
+#define DMA_ID_TLB_PSI_FLUSH   (((u64)3) << 3)
+#define DMA_ID_TLB_READ_DRAIN  (((u64)1) << 7)
+#define DMA_ID_TLB_WRITE_DRAIN (((u64)1) << 6)
+#define DMA_ID_TLB_DID(id)     (((u64)((id & 0xffff) << 16)))
+#define DMA_ID_TLB_IH_NONLEAF  (((u64)1) << 6)
+#define DMA_ID_TLB_ADDR(addr)  (addr)
+#define DMA_ID_TLB_ADDR_MASK(mask)     (mask)
+
 /* PMEN_REG */
 #define DMA_PMEN_EPM (((u32)1)<<31)
 #define DMA_PMEN_PRS (((u32)1)<<0)
@@ -151,6 +160,9 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
 #define DMA_GCMD_SFL (((u32)1) << 29)
 #define DMA_GCMD_EAFL (((u32)1) << 28)
 #define DMA_GCMD_WBF (((u32)1) << 27)
+#define DMA_GCMD_QIE (((u32)1) << 26)
+#define DMA_GCMD_SIRTP (((u32)1) << 24)
+#define DMA_GCMD_IRE (((u32) 1) << 25)
 
 /* GSTS_REG */
 #define DMA_GSTS_TES (((u32)1) << 31)
@@ -158,6 +170,9 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
 #define DMA_GSTS_FLS (((u32)1) << 29)
 #define DMA_GSTS_AFLS (((u32)1) << 28)
 #define DMA_GSTS_WBFS (((u32)1) << 27)
+#define DMA_GSTS_QIES (((u32)1) << 26)
+#define DMA_GSTS_IRTPS (((u32)1) << 24)
+#define DMA_GSTS_IRES (((u32)1) << 25)
 
 /* CCMD_REG */
 #define DMA_CCMD_ICC (((u64)1) << 63)
@@ -187,158 +202,106 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
 #define dma_frcd_source_id(c) (c & 0xffff)
 #define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */
 
-/*
- * 0: Present
- * 1-11: Reserved
- * 12-63: Context Ptr (12 - (haw-1))
- * 64-127: Reserved
- */
-struct root_entry {
-       u64     val;
-       u64     rsvd1;
-};
-#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry))
-static inline bool root_present(struct root_entry *root)
-{
-       return (root->val & 1);
-}
-static inline void set_root_present(struct root_entry *root)
-{
-       root->val |= 1;
-}
-static inline void set_root_value(struct root_entry *root, unsigned long value)
-{
-       root->val |= value & PAGE_MASK_4K;
+#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) /* 10sec */
+
+#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \
+{\
+       cycles_t start_time = get_cycles();\
+       while (1) {\
+               sts = op (iommu->reg + offset);\
+               if (cond)\
+                       break;\
+               if (DMAR_OPERATION_TIMEOUT < (get_cycles() - start_time))\
+                       panic("DMAR hardware is malfunctioning\n");\
+               cpu_relax();\
+       }\
 }
 
-struct context_entry;
-static inline struct context_entry *
-get_context_addr_from_root(struct root_entry *root)
-{
-       return (struct context_entry *)
-               (root_present(root)?phys_to_virt(
-               root->val & PAGE_MASK_4K):
-               NULL);
-}
-
-/*
- * low 64 bits:
- * 0: present
- * 1: fault processing disable
- * 2-3: translation type
- * 12-63: address space root
- * high 64 bits:
- * 0-2: address width
- * 3-6: aval
- * 8-23: domain id
- */
-struct context_entry {
-       u64 lo;
-       u64 hi;
-};
-#define context_present(c) ((c).lo & 1)
-#define context_fault_disable(c) (((c).lo >> 1) & 1)
-#define context_translation_type(c) (((c).lo >> 2) & 3)
-#define context_address_root(c) ((c).lo & PAGE_MASK_4K)
-#define context_address_width(c) ((c).hi &  7)
-#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1))
-
-#define context_set_present(c) do {(c).lo |= 1;} while (0)
-#define context_set_fault_enable(c) \
-       do {(c).lo &= (((u64)-1) << 2) | 1;} while (0)
-#define context_set_translation_type(c, val) \
-       do { \
-               (c).lo &= (((u64)-1) << 4) | 3; \
-               (c).lo |= ((val) & 3) << 2; \
-       } while (0)
-#define CONTEXT_TT_MULTI_LEVEL 0
-#define context_set_address_root(c, val) \
-       do {(c).lo |= (val) & PAGE_MASK_4K;} while (0)
-#define context_set_address_width(c, val) do {(c).hi |= (val) & 7;} while (0)
-#define context_set_domain_id(c, val) \
-       do {(c).hi |= ((val) & ((1 << 16) - 1)) << 8;} while (0)
-#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while (0)
+#define QI_LENGTH      256     /* queue length */
 
-/*
- * 0: readable
- * 1: writable
- * 2-6: reserved
- * 7: super page
- * 8-11: available
- * 12-63: Host physcial address
- */
-struct dma_pte {
-       u64 val;
+enum {
+       QI_FREE,
+       QI_IN_USE,
+       QI_DONE
 };
-#define dma_clear_pte(p)       do {(p).val = 0;} while (0)
-
-#define DMA_PTE_READ (1)
-#define DMA_PTE_WRITE (2)
 
-#define dma_set_pte_readable(p) do {(p).val |= DMA_PTE_READ;} while (0)
-#define dma_set_pte_writable(p) do {(p).val |= DMA_PTE_WRITE;} while (0)
-#define dma_set_pte_prot(p, prot) \
-               do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0)
-#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
-#define dma_set_pte_addr(p, addr) do {\
-               (p).val |= ((addr) & PAGE_MASK_4K); } while (0)
-#define dma_pte_present(p) (((p).val & 3) != 0)
+#define QI_CC_TYPE             0x1
+#define QI_IOTLB_TYPE          0x2
+#define QI_DIOTLB_TYPE         0x3
+#define QI_IEC_TYPE            0x4
+#define QI_IWD_TYPE            0x5
 
-struct intel_iommu;
+#define QI_IEC_SELECTIVE       (((u64)1) << 4)
+#define QI_IEC_IIDEX(idx)      (((u64)(idx & 0xffff) << 32))
+#define QI_IEC_IM(m)           (((u64)(m & 0x1f) << 27))
 
-struct dmar_domain {
-       int     id;                     /* domain id */
-       struct intel_iommu *iommu;      /* back pointer to owning iommu */
+#define QI_IWD_STATUS_DATA(d)  (((u64)d) << 32)
+#define QI_IWD_STATUS_WRITE    (((u64)1) << 5)
 
-       struct list_head devices;       /* all devices' list */
-       struct iova_domain iovad;       /* iova's that belong to this domain */
+struct qi_desc {
+       u64 low, high;
+};
 
-       struct dma_pte  *pgd;           /* virtual address */
-       spinlock_t      mapping_lock;   /* page table lock */
-       int             gaw;            /* max guest address width */
+struct q_inval {
+       spinlock_t      q_lock;
+       struct qi_desc  *desc;          /* invalidation queue */
+       int             *desc_status;   /* desc status */
+       int             free_head;      /* first free entry */
+       int             free_tail;      /* last free entry */
+       int             free_cnt;
+};
 
-       /* adjusted guest address width, 0 is level 2 30-bit */
-       int             agaw;
+#ifdef CONFIG_INTR_REMAP
+/* 1MB - maximum possible interrupt remapping table size */
+#define INTR_REMAP_PAGE_ORDER  8
+#define INTR_REMAP_TABLE_REG_SIZE      0xf
 
-#define DOMAIN_FLAG_MULTIPLE_DEVICES 1
-       int             flags;
-};
+#define INTR_REMAP_TABLE_ENTRIES       65536
 
-/* PCI domain-device relationship */
-struct device_domain_info {
-       struct list_head link;  /* link to domain siblings */
-       struct list_head global; /* link to global list */
-       u8 bus;                 /* PCI bus numer */
-       u8 devfn;               /* PCI devfn number */
-       struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */
-       struct dmar_domain *domain; /* pointer to domain */
+struct ir_table {
+       struct irte *base;
 };
-
-extern int init_dmars(void);
+#endif
 
 struct intel_iommu {
        void __iomem    *reg; /* Pointer to hardware regs, virtual addr */
        u64             cap;
        u64             ecap;
-       unsigned long   *domain_ids; /* bitmap of domains */
-       struct dmar_domain **domains; /* ptr to domains */
        int             seg;
        u32             gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
-       spinlock_t      lock; /* protect context, domain ids */
        spinlock_t      register_lock; /* protect register handling */
+       int             seq_id; /* sequence id of the iommu */
+
+#ifdef CONFIG_DMAR
+       unsigned long   *domain_ids; /* bitmap of domains */
+       struct dmar_domain **domains; /* ptr to domains */
+       spinlock_t      lock; /* protect context, domain ids */
        struct root_entry *root_entry; /* virtual address */
 
        unsigned int irq;
        unsigned char name[7];    /* Device Name */
        struct msi_msg saved_msg;
        struct sys_device sysdev;
+#endif
+       struct q_inval  *qi;            /* Queued invalidation info */
+#ifdef CONFIG_INTR_REMAP
+       struct ir_table *ir_table;      /* Interrupt remapping info */
+#endif
 };
 
-#ifndef CONFIG_DMAR_GFX_WA
-static inline void iommu_prepare_gfx_mapping(void)
+static inline void __iommu_flush_cache(
+       struct intel_iommu *iommu, void *addr, int size)
 {
-       return;
+       if (!ecap_coherent(iommu->ecap))
+               clflush_cache_range(addr, size);
 }
-#endif /* !CONFIG_DMAR_GFX_WA */
 
+extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
+
+extern int alloc_iommu(struct dmar_drhd_unit *drhd);
+extern void free_iommu(struct intel_iommu *iommu);
+extern int dmar_enable_qi(struct intel_iommu *iommu);
+extern void qi_global_iec(struct intel_iommu *iommu);
+
+extern void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
 #endif
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
new file mode 100644 (file)
index 0000000..bb642cc
--- /dev/null
@@ -0,0 +1,471 @@
+#include <linux/dmar.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <asm/io_apic.h>
+#include "intel-iommu.h"
+#include "intr_remapping.h"
+
+static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
+static int ir_ioapic_num;
+int intr_remapping_enabled;
+
+static struct {
+       struct intel_iommu *iommu;
+       u16 irte_index;
+       u16 sub_handle;
+       u8  irte_mask;
+} irq_2_iommu[NR_IRQS];
+
+static DEFINE_SPINLOCK(irq_2_ir_lock);
+
+int irq_remapped(int irq)
+{
+       if (irq > NR_IRQS)
+               return 0;
+
+       if (!irq_2_iommu[irq].iommu)
+               return 0;
+
+       return 1;
+}
+
+int get_irte(int irq, struct irte *entry)
+{
+       int index;
+
+       if (!entry || irq > NR_IRQS)
+               return -1;
+
+       spin_lock(&irq_2_ir_lock);
+       if (!irq_2_iommu[irq].iommu) {
+               spin_unlock(&irq_2_ir_lock);
+               return -1;
+       }
+
+       index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
+       *entry = *(irq_2_iommu[irq].iommu->ir_table->base + index);
+
+       spin_unlock(&irq_2_ir_lock);
+       return 0;
+}
+
+int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
+{
+       struct ir_table *table = iommu->ir_table;
+       u16 index, start_index;
+       unsigned int mask = 0;
+       int i;
+
+       if (!count)
+               return -1;
+
+       /*
+        * start the IRTE search from index 0.
+        */
+       index = start_index = 0;
+
+       if (count > 1) {
+               count = __roundup_pow_of_two(count);
+               mask = ilog2(count);
+       }
+
+       if (mask > ecap_max_handle_mask(iommu->ecap)) {
+               printk(KERN_ERR
+                      "Requested mask %x exceeds the max invalidation handle"
+                      " mask value %Lx\n", mask,
+                      ecap_max_handle_mask(iommu->ecap));
+               return -1;
+       }
+
+       spin_lock(&irq_2_ir_lock);
+       do {
+               for (i = index; i < index + count; i++)
+                       if  (table->base[i].present)
+                               break;
+               /* empty index found */
+               if (i == index + count)
+                       break;
+
+               index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
+
+               if (index == start_index) {
+                       spin_unlock(&irq_2_ir_lock);
+                       printk(KERN_ERR "can't allocate an IRTE\n");
+                       return -1;
+               }
+       } while (1);
+
+       for (i = index; i < index + count; i++)
+               table->base[i].present = 1;
+
+       irq_2_iommu[irq].iommu = iommu;
+       irq_2_iommu[irq].irte_index =  index;
+       irq_2_iommu[irq].sub_handle = 0;
+       irq_2_iommu[irq].irte_mask = mask;
+
+       spin_unlock(&irq_2_ir_lock);
+
+       return index;
+}
+
+static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
+{
+       struct qi_desc desc;
+
+       desc.low = QI_IEC_IIDEX(index) | QI_IEC_TYPE | QI_IEC_IM(mask)
+                  | QI_IEC_SELECTIVE;
+       desc.high = 0;
+
+       qi_submit_sync(&desc, iommu);
+}
+
+int map_irq_to_irte_handle(int irq, u16 *sub_handle)
+{
+       int index;
+
+       spin_lock(&irq_2_ir_lock);
+       if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+               spin_unlock(&irq_2_ir_lock);
+               return -1;
+       }
+
+       *sub_handle = irq_2_iommu[irq].sub_handle;
+       index = irq_2_iommu[irq].irte_index;
+       spin_unlock(&irq_2_ir_lock);
+       return index;
+}
+
+int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
+{
+       spin_lock(&irq_2_ir_lock);
+       if (irq >= NR_IRQS || irq_2_iommu[irq].iommu) {
+               spin_unlock(&irq_2_ir_lock);
+               return -1;
+       }
+
+       irq_2_iommu[irq].iommu = iommu;
+       irq_2_iommu[irq].irte_index = index;
+       irq_2_iommu[irq].sub_handle = subhandle;
+       irq_2_iommu[irq].irte_mask = 0;
+
+       spin_unlock(&irq_2_ir_lock);
+
+       return 0;
+}
+
+int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
+{
+       spin_lock(&irq_2_ir_lock);
+       if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+               spin_unlock(&irq_2_ir_lock);
+               return -1;
+       }
+
+       irq_2_iommu[irq].iommu = NULL;
+       irq_2_iommu[irq].irte_index = 0;
+       irq_2_iommu[irq].sub_handle = 0;
+       irq_2_iommu[irq].irte_mask = 0;
+
+       spin_unlock(&irq_2_ir_lock);
+
+       return 0;
+}
+
+int modify_irte(int irq, struct irte *irte_modified)
+{
+       int index;
+       struct irte *irte;
+       struct intel_iommu *iommu;
+
+       spin_lock(&irq_2_ir_lock);
+       if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+               spin_unlock(&irq_2_ir_lock);
+               return -1;
+       }
+
+       iommu = irq_2_iommu[irq].iommu;
+
+       index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
+       irte = &iommu->ir_table->base[index];
+
+       set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1));
+       __iommu_flush_cache(iommu, irte, sizeof(*irte));
+
+       qi_flush_iec(iommu, index, 0);
+
+       spin_unlock(&irq_2_ir_lock);
+       return 0;
+}
+
+int flush_irte(int irq)
+{
+       int index;
+       struct intel_iommu *iommu;
+
+       spin_lock(&irq_2_ir_lock);
+       if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+               spin_unlock(&irq_2_ir_lock);
+               return -1;
+       }
+
+       iommu = irq_2_iommu[irq].iommu;
+
+       index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
+
+       qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask);
+       spin_unlock(&irq_2_ir_lock);
+
+       return 0;
+}
+
+struct intel_iommu *map_ioapic_to_ir(int apic)
+{
+       int i;
+
+       for (i = 0; i < MAX_IO_APICS; i++)
+               if (ir_ioapic[i].id == apic)
+                       return ir_ioapic[i].iommu;
+       return NULL;
+}
+
+struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
+{
+       struct dmar_drhd_unit *drhd;
+
+       drhd = dmar_find_matched_drhd_unit(dev);
+       if (!drhd)
+               return NULL;
+
+       return drhd->iommu;
+}
+
+int free_irte(int irq)
+{
+       int index, i;
+       struct irte *irte;
+       struct intel_iommu *iommu;
+
+       spin_lock(&irq_2_ir_lock);
+       if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+               spin_unlock(&irq_2_ir_lock);
+               return -1;
+       }
+
+       iommu = irq_2_iommu[irq].iommu;
+
+       index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
+       irte = &iommu->ir_table->base[index];
+
+       if (!irq_2_iommu[irq].sub_handle) {
+               for (i = 0; i < (1 << irq_2_iommu[irq].irte_mask); i++)
+                       set_64bit((unsigned long *)irte, 0);
+               qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask);
+       }
+
+       irq_2_iommu[irq].iommu = NULL;
+       irq_2_iommu[irq].irte_index = 0;
+       irq_2_iommu[irq].sub_handle = 0;
+       irq_2_iommu[irq].irte_mask = 0;
+
+       spin_unlock(&irq_2_ir_lock);
+
+       return 0;
+}
+
+static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
+{
+       u64 addr;
+       u32 cmd, sts;
+       unsigned long flags;
+
+       addr = virt_to_phys((void *)iommu->ir_table->base);
+
+       spin_lock_irqsave(&iommu->register_lock, flags);
+
+       dmar_writeq(iommu->reg + DMAR_IRTA_REG,
+                   (addr) | IR_X2APIC_MODE(mode) | INTR_REMAP_TABLE_REG_SIZE);
+
+       /* Set interrupt-remapping table pointer */
+       cmd = iommu->gcmd | DMA_GCMD_SIRTP;
+       writel(cmd, iommu->reg + DMAR_GCMD_REG);
+
+       IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+                     readl, (sts & DMA_GSTS_IRTPS), sts);
+       spin_unlock_irqrestore(&iommu->register_lock, flags);
+
+       /*
+        * global invalidation of interrupt entry cache before enabling
+        * interrupt-remapping.
+        */
+       qi_global_iec(iommu);
+
+       spin_lock_irqsave(&iommu->register_lock, flags);
+
+       /* Enable interrupt-remapping */
+       cmd = iommu->gcmd | DMA_GCMD_IRE;
+       iommu->gcmd |= DMA_GCMD_IRE;
+       writel(cmd, iommu->reg + DMAR_GCMD_REG);
+
+       IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+                     readl, (sts & DMA_GSTS_IRES), sts);
+
+       spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
+
+static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
+{
+       struct ir_table *ir_table;
+       struct page *pages;
+
+       ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table),
+                                            GFP_KERNEL);
+
+       if (!iommu->ir_table)
+               return -ENOMEM;
+
+       pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, INTR_REMAP_PAGE_ORDER);
+
+       if (!pages) {
+               printk(KERN_ERR "failed to allocate pages of order %d\n",
+                      INTR_REMAP_PAGE_ORDER);
+               kfree(iommu->ir_table);
+               return -ENOMEM;
+       }
+
+       ir_table->base = page_address(pages);
+
+       iommu_set_intr_remapping(iommu, mode);
+       return 0;
+}
+
+int __init enable_intr_remapping(int eim)
+{
+       struct dmar_drhd_unit *drhd;
+       int setup = 0;
+
+       /*
+        * check for the Interrupt-remapping support
+        */
+       for_each_drhd_unit(drhd) {
+               struct intel_iommu *iommu = drhd->iommu;
+
+               if (!ecap_ir_support(iommu->ecap))
+                       continue;
+
+               if (eim && !ecap_eim_support(iommu->ecap)) {
+                       printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
+                              " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
+                       return -1;
+               }
+       }
+
+       /*
+        * Enable queued invalidation for all the DRHD's.
+        */
+       for_each_drhd_unit(drhd) {
+               int ret;
+               struct intel_iommu *iommu = drhd->iommu;
+               ret = dmar_enable_qi(iommu);
+
+               if (ret) {
+                       printk(KERN_ERR "DRHD %Lx: failed to enable queued, "
+                              " invalidation, ecap %Lx, ret %d\n",
+                              drhd->reg_base_addr, iommu->ecap, ret);
+                       return -1;
+               }
+       }
+
+       /*
+        * Setup Interrupt-remapping for all the DRHD's now.
+        */
+       for_each_drhd_unit(drhd) {
+               struct intel_iommu *iommu = drhd->iommu;
+
+               if (!ecap_ir_support(iommu->ecap))
+                       continue;
+
+               if (setup_intr_remapping(iommu, eim))
+                       goto error;
+
+               setup = 1;
+       }
+
+       if (!setup)
+               goto error;
+
+       intr_remapping_enabled = 1;
+
+       return 0;
+
+error:
+       /*
+        * handle error condition gracefully here!
+        */
+       return -1;
+}
+
+static int ir_parse_ioapic_scope(struct acpi_dmar_header *header,
+                                struct intel_iommu *iommu)
+{
+       struct acpi_dmar_hardware_unit *drhd;
+       struct acpi_dmar_device_scope *scope;
+       void *start, *end;
+
+       drhd = (struct acpi_dmar_hardware_unit *)header;
+
+       start = (void *)(drhd + 1);
+       end = ((void *)drhd) + header->length;
+
+       while (start < end) {
+               scope = start;
+               if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
+                       if (ir_ioapic_num == MAX_IO_APICS) {
+                               printk(KERN_WARNING "Exceeded Max IO APICS\n");
+                               return -1;
+                       }
+
+                       printk(KERN_INFO "IOAPIC id %d under DRHD base"
+                              " 0x%Lx\n", scope->enumeration_id,
+                              drhd->address);
+
+                       ir_ioapic[ir_ioapic_num].iommu = iommu;
+                       ir_ioapic[ir_ioapic_num].id = scope->enumeration_id;
+                       ir_ioapic_num++;
+               }
+               start += scope->length;
+       }
+
+       return 0;
+}
+
+/*
+ * Finds the assocaition between IOAPIC's and its Interrupt-remapping
+ * hardware unit.
+ */
+int __init parse_ioapics_under_ir(void)
+{
+       struct dmar_drhd_unit *drhd;
+       int ir_supported = 0;
+
+       for_each_drhd_unit(drhd) {
+               struct intel_iommu *iommu = drhd->iommu;
+
+               if (ecap_ir_support(iommu->ecap)) {
+                       if (ir_parse_ioapic_scope(drhd->hdr, iommu))
+                               return -1;
+
+                       ir_supported = 1;
+               }
+       }
+
+       if (ir_supported && ir_ioapic_num != nr_ioapics) {
+               printk(KERN_WARNING
+                      "Not all IO-APIC's listed under remapping hardware\n");
+               return -1;
+       }
+
+       return ir_supported;
+}
diff --git a/drivers/pci/intr_remapping.h b/drivers/pci/intr_remapping.h
new file mode 100644 (file)
index 0000000..05f2635
--- /dev/null
@@ -0,0 +1,8 @@
+#include "intel-iommu.h"
+
+struct ioapic_scope {
+       struct intel_iommu *iommu;
+       unsigned int id;
+};
+
+#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
index 73a86d09bba8d71dd84641e58dbde5d1c1278d03..9c129248466c024dd7b03411b6f4351d707823e0 100644 (file)
@@ -7,13 +7,13 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/of_device.h>
 
 #include <asm/system.h>
 #include <asm/sbus.h>
 #include <asm/dma.h>
 #include <asm/oplib.h>
 #include <asm/prom.h>
-#include <asm/of_device.h>
 #include <asm/bpp.h>
 #include <asm/irq.h>
 
index aeeec5588afd48c2573097417f6fc428d0f6b39d..e41766d08035643e18b72a2cfb88bf471355d885 100644 (file)
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/of_device.h>
 
 #include <asm/hypervisor.h>
 #include <asm/spitfire.h>
 #include <asm/prom.h>
-#include <asm/of_device.h>
 #include <asm/irq.h>
 
 #if defined(CONFIG_MAGIC_SYSRQ)
index 15ee497e1c78805e3030cd41f383864070884980..29b4458abf744601f39a672bcb0333f5c92b519d 100644 (file)
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/of_device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
-#include <asm/of_device.h>
 
 #if defined(CONFIG_SERIAL_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
index e24e68235088855c719c629f37a020f5d78d0e54..a378464f92927e83fde05e4e236eaa4f413f1aa5 100644 (file)
 #include <linux/serial_reg.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/of_device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
-#include <asm/of_device.h>
 
 #if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
index 0f3d69b86d6795de97bc81239d20fb78cbb920e9..3cb4c8aee13fa74461648ff3a4ec9f12380fbba3 100644 (file)
 #include <linux/serio.h>
 #endif
 #include <linux/init.h>
+#include <linux/of_device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
-#include <asm/of_device.h>
 
 #if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
index 755823cdf62a992b83d24fb894d186ed58e0761e..bcefbddeba5099877981a1717cfd22edfd35e159 100644 (file)
@@ -95,16 +95,18 @@ config USB
 
 source "drivers/usb/core/Kconfig"
 
+source "drivers/usb/mon/Kconfig"
+
 source "drivers/usb/host/Kconfig"
 
+source "drivers/usb/musb/Kconfig"
+
 source "drivers/usb/class/Kconfig"
 
 source "drivers/usb/storage/Kconfig"
 
 source "drivers/usb/image/Kconfig"
 
-source "drivers/usb/mon/Kconfig"
-
 comment "USB port drivers"
        depends on USB
 
index 507a9bd0d77caa6267caa7c52f4c108a5082c959..9aea43a8c4adce959b3aafcc1b171f807b2fc1a7 100644 (file)
@@ -602,7 +602,7 @@ static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_requ
                        offd = le32_to_cpu(buf[offb++]);
                        if (offd >= size) {
                                if (printk_ratelimit())
-                                       usb_err(instance->usbatm, "wrong index #%x in response to cm #%x\n",
+                                       usb_err(instance->usbatm, "wrong index %#x in response to cm %#x\n",
                                                offd, cm);
                                ret = -EIO;
                                goto cleanup;
index 0725b1871f23f757b8012dde88cb08ee90e9b3b7..efc4373ededb4ea1f15a31f8c32716f1333be6a2 100644 (file)
@@ -51,6 +51,7 @@
  */
 
 #undef DEBUG
+#undef VERBOSE_DEBUG
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -70,6 +71,9 @@
 
 #include "cdc-acm.h"
 
+
+#define ACM_CLOSE_TIMEOUT      15      /* seconds to let writes drain */
+
 /*
  * Version Information
  */
@@ -85,6 +89,12 @@ static DEFINE_MUTEX(open_mutex);
 
 #define ACM_READY(acm) (acm && acm->dev && acm->used)
 
+#ifdef VERBOSE_DEBUG
+#define verbose        1
+#else
+#define verbose        0
+#endif
+
 /*
  * Functions for ACM control messages.
  */
@@ -136,19 +146,17 @@ static int acm_wb_alloc(struct acm *acm)
 static int acm_wb_is_avail(struct acm *acm)
 {
        int i, n;
+       unsigned long flags;
 
        n = ACM_NW;
+       spin_lock_irqsave(&acm->write_lock, flags);
        for (i = 0; i < ACM_NW; i++) {
                n -= acm->wb[i].use;
        }
+       spin_unlock_irqrestore(&acm->write_lock, flags);
        return n;
 }
 
-static inline int acm_wb_is_used(struct acm *acm, int wbn)
-{
-       return acm->wb[wbn].use;
-}
-
 /*
  * Finish write.
  */
@@ -157,7 +165,6 @@ static void acm_write_done(struct acm *acm, struct acm_wb *wb)
        unsigned long flags;
 
        spin_lock_irqsave(&acm->write_lock, flags);
-       acm->write_ready = 1;
        wb->use = 0;
        acm->transmitting--;
        spin_unlock_irqrestore(&acm->write_lock, flags);
@@ -190,40 +197,25 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb)
 static int acm_write_start(struct acm *acm, int wbn)
 {
        unsigned long flags;
-       struct acm_wb *wb;
+       struct acm_wb *wb = &acm->wb[wbn];
        int rc;
 
        spin_lock_irqsave(&acm->write_lock, flags);
        if (!acm->dev) {
+               wb->use = 0;
                spin_unlock_irqrestore(&acm->write_lock, flags);
                return -ENODEV;
        }
 
-       if (!acm->write_ready) {
-               spin_unlock_irqrestore(&acm->write_lock, flags);
-               return 0;       /* A white lie */
-       }
-
-       wb = &acm->wb[wbn];
-       if(acm_wb_is_avail(acm) <= 1)
-               acm->write_ready = 0;
-
        dbg("%s susp_count: %d", __func__, acm->susp_count);
        if (acm->susp_count) {
-               acm->old_ready = acm->write_ready;
                acm->delayed_wb = wb;
-               acm->write_ready = 0;
                schedule_work(&acm->waker);
                spin_unlock_irqrestore(&acm->write_lock, flags);
                return 0;       /* A white lie */
        }
        usb_mark_last_busy(acm->dev);
 
-       if (!acm_wb_is_used(acm, wbn)) {
-               spin_unlock_irqrestore(&acm->write_lock, flags);
-               return 0;
-       }
-
        rc = acm_start_wb(acm, wb);
        spin_unlock_irqrestore(&acm->write_lock, flags);
 
@@ -488,22 +480,28 @@ urbs:
 /* data interface wrote those outgoing bytes */
 static void acm_write_bulk(struct urb *urb)
 {
-       struct acm *acm;
        struct acm_wb *wb = urb->context;
+       struct acm *acm = wb->instance;
 
-       dbg("Entering acm_write_bulk with status %d", urb->status);
+       if (verbose || urb->status
+                       || (urb->actual_length != urb->transfer_buffer_length))
+               dev_dbg(&acm->data->dev, "tx %d/%d bytes -- > %d\n",
+                       urb->actual_length,
+                       urb->transfer_buffer_length,
+                       urb->status);
 
-       acm = wb->instance;
        acm_write_done(acm, wb);
        if (ACM_READY(acm))
                schedule_work(&acm->work);
+       else
+               wake_up_interruptible(&acm->drain_wait);
 }
 
 static void acm_softint(struct work_struct *work)
 {
        struct acm *acm = container_of(work, struct acm, work);
-       dbg("Entering acm_softint.");
-       
+
+       dev_vdbg(&acm->data->dev, "tx work\n");
        if (!ACM_READY(acm))
                return;
        tty_wakeup(acm->tty);
@@ -512,7 +510,6 @@ static void acm_softint(struct work_struct *work)
 static void acm_waker(struct work_struct *waker)
 {
        struct acm *acm = container_of(waker, struct acm, waker);
-       long flags;
        int rv;
 
        rv = usb_autopm_get_interface(acm->control);
@@ -524,9 +521,6 @@ static void acm_waker(struct work_struct *waker)
                acm_start_wb(acm, acm->delayed_wb);
                acm->delayed_wb = NULL;
        }
-       spin_lock_irqsave(&acm->write_lock, flags);
-       acm->write_ready = acm->old_ready;
-       spin_unlock_irqrestore(&acm->write_lock, flags);
        usb_autopm_put_interface(acm->control);
 }
 
@@ -628,6 +622,8 @@ static void acm_tty_unregister(struct acm *acm)
        kfree(acm);
 }
 
+static int acm_tty_chars_in_buffer(struct tty_struct *tty);
+
 static void acm_tty_close(struct tty_struct *tty, struct file *filp)
 {
        struct acm *acm = tty->driver_data;
@@ -642,6 +638,13 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
                if (acm->dev) {
                        usb_autopm_get_interface(acm->control);
                        acm_set_control(acm, acm->ctrlout = 0);
+
+                       /* try letting the last writes drain naturally */
+                       wait_event_interruptible_timeout(acm->drain_wait,
+                                       (ACM_NW == acm_wb_is_avail(acm))
+                                               || !acm->dev,
+                                       ACM_CLOSE_TIMEOUT * HZ);
+
                        usb_kill_urb(acm->ctrlurb);
                        for (i = 0; i < ACM_NW; i++)
                                usb_kill_urb(acm->wb[i].urb);
@@ -697,7 +700,7 @@ static int acm_tty_write_room(struct tty_struct *tty)
         * Do not let the line discipline to know that we have a reserve,
         * or it might get too enthusiastic.
         */
-       return (acm->write_ready && acm_wb_is_avail(acm)) ? acm->writesize : 0;
+       return acm_wb_is_avail(acm) ? acm->writesize : 0;
 }
 
 static int acm_tty_chars_in_buffer(struct tty_struct *tty)
@@ -1072,11 +1075,11 @@ skip_normal_probe:
        acm->urb_task.data = (unsigned long) acm;
        INIT_WORK(&acm->work, acm_softint);
        INIT_WORK(&acm->waker, acm_waker);
+       init_waitqueue_head(&acm->drain_wait);
        spin_lock_init(&acm->throttle_lock);
        spin_lock_init(&acm->write_lock);
        spin_lock_init(&acm->read_lock);
        mutex_init(&acm->mutex);
-       acm->write_ready = 1;
        acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
 
        buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
@@ -1108,9 +1111,11 @@ skip_normal_probe:
                rcv->instance = acm;
        }
        for (i = 0; i < num_rx_buf; i++) {
-               struct acm_rb *buf = &(acm->rb[i]);
+               struct acm_rb *rb = &(acm->rb[i]);
 
-               if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
+               rb->base = usb_buffer_alloc(acm->dev, readsize,
+                               GFP_KERNEL, &rb->dma);
+               if (!rb->base) {
                        dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
                        goto alloc_fail7;
                }
@@ -1172,6 +1177,7 @@ skip_countries:
        acm_set_line(acm, &acm->line);
 
        usb_driver_claim_interface(&acm_driver, data_interface, acm);
+       usb_set_intfdata(data_interface, acm);
 
        usb_get_intf(control_interface);
        tty_register_device(acm_tty_driver, minor, &control_interface->dev);
@@ -1221,11 +1227,11 @@ static void acm_disconnect(struct usb_interface *intf)
        struct acm *acm = usb_get_intfdata(intf);
        struct usb_device *usb_dev = interface_to_usbdev(intf);
 
-       mutex_lock(&open_mutex);
-       if (!acm || !acm->dev) {
-               mutex_unlock(&open_mutex);
+       /* sibling interface is already cleaning up */
+       if (!acm)
                return;
-       }
+
+       mutex_lock(&open_mutex);
        if (acm->country_codes){
                device_remove_file(&acm->control->dev,
                                &dev_attr_wCountryCodes);
index 85c3aaaab7c58570ec0155e0cbd37590cb0a4472..1f95e7aa1b665618bc1fa83f6b9977375a026298 100644 (file)
@@ -106,8 +106,6 @@ struct acm {
        struct list_head spare_read_bufs;
        struct list_head filled_read_bufs;
        int write_used;                                 /* number of non-empty write buffers */
-       int write_ready;                                /* write urb is not running */
-       int old_ready;
        int processing;
        int transmitting;
        spinlock_t write_lock;
@@ -115,6 +113,7 @@ struct acm {
        struct usb_cdc_line_coding line;                /* bits, stop, parity */
        struct work_struct work;                        /* work queue entry for line discipline waking up */
        struct work_struct waker;
+       wait_queue_head_t drain_wait;                   /* close processing */
        struct tasklet_struct urb_task;                 /* rx processing */
        spinlock_t throttle_lock;                       /* synchronize throtteling and read callback */
        unsigned int ctrlin;                            /* input control lines (DCD, DSR, RI, break, overruns) */
index ddb54e14a5c54595908b4773f125db97c3e550e5..2be37fe466f2f56d5d2adfbd94ebd3ec5ba2cd6f 100644 (file)
@@ -774,7 +774,6 @@ void usb_deregister(struct usb_driver *driver)
 }
 EXPORT_SYMBOL_GPL(usb_deregister);
 
-
 /* Forced unbinding of a USB interface driver, either because
  * it doesn't support pre_reset/post_reset/reset_resume or
  * because it doesn't support suspend/resume.
@@ -821,6 +820,8 @@ void usb_rebind_intf(struct usb_interface *intf)
                dev_warn(&intf->dev, "rebind failed: %d\n", rc);
 }
 
+#ifdef CONFIG_PM
+
 #define DO_UNBIND      0
 #define DO_REBIND      1
 
@@ -872,8 +873,6 @@ static void do_unbind_rebind(struct usb_device *udev, int action)
        }
 }
 
-#ifdef CONFIG_PM
-
 /* Caller has locked udev's pm_mutex */
 static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
 {
index 586d6f1376cf7700a677825b41523dc056b8c900..286b4431a0974195dc0ceffe74f351d18f1d7c68 100644 (file)
@@ -1091,8 +1091,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
                                continue;
                        dev_dbg(&dev->dev, "unregistering interface %s\n",
                                dev_name(&interface->dev));
-                       device_del(&interface->dev);
                        usb_remove_sysfs_intf_files(interface);
+                       device_del(&interface->dev);
                }
 
                /* Now that the interfaces are unbound, nobody should
index c6a8c6b1116a45381d5ee4acb98bbda541d36ae8..acc95b2ac6f85ad24c9fc067bdc511a3e50a9589 100644 (file)
@@ -284,6 +284,16 @@ config USB_LH7A40X
        default USB_GADGET
        select USB_GADGET_SELECTED
 
+# built in ../musb along with host support
+config USB_GADGET_MUSB_HDRC
+       boolean "Inventra HDRC USB Peripheral (TI, ...)"
+       depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
+       select USB_GADGET_DUALSPEED
+       select USB_GADGET_SELECTED
+       help
+         This OTG-capable silicon IP is used in dual designs including
+         the TI DaVinci, OMAP 243x, OMAP 343x, and TUSB 6010.
+
 config USB_GADGET_OMAP
        boolean "OMAP USB Device Controller"
        depends on ARCH_OMAP
index 21d1406af9ee04f8e07d3afe0b073fd6df02bdaf..7600a0c787532fab60362fa9c912f7e702a8fcaa 100644 (file)
@@ -542,13 +542,14 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
                req->req.context = dum;
                req->req.complete = fifo_complete;
 
+               list_add_tail(&req->queue, &ep->queue);
                spin_unlock (&dum->lock);
                _req->actual = _req->length;
                _req->status = 0;
                _req->complete (_ep, _req);
                spin_lock (&dum->lock);
-       }
-       list_add_tail (&req->queue, &ep->queue);
+       }  else
+               list_add_tail(&req->queue, &ep->queue);
        spin_unlock_irqrestore (&dum->lock, flags);
 
        /* real hardware would likely enable transfers here, in case
index d8faccf278959b531e3a075267c3687edeb5f009..5ee1590b8e9cf2739e629804193aa8fa053954cf 100644 (file)
@@ -47,18 +47,37 @@ struct f_acm {
        u8                              ctrl_id, data_id;
        u8                              port_num;
 
-       struct usb_descriptor_header    **fs_function;
+       u8                              pending;
+
+       /* lock is mostly for pending and notify_req ... they get accessed
+        * by callbacks both from tty (open/close/break) under its spinlock,
+        * and notify_req.complete() which can't use that lock.
+        */
+       spinlock_t                      lock;
+
        struct acm_ep_descs             fs;
-       struct usb_descriptor_header    **hs_function;
        struct acm_ep_descs             hs;
 
        struct usb_ep                   *notify;
        struct usb_endpoint_descriptor  *notify_desc;
+       struct usb_request              *notify_req;
 
        struct usb_cdc_line_coding      port_line_coding;       /* 8-N-1 etc */
+
+       /* SetControlLineState request -- CDC 1.1 section 6.2.14 (INPUT) */
        u16                             port_handshake_bits;
-#define RS232_RTS      (1 << 1)        /* unused with full duplex */
-#define RS232_DTR      (1 << 0)        /* host is ready for data r/w */
+#define ACM_CTRL_RTS   (1 << 1)        /* unused with full duplex */
+#define ACM_CTRL_DTR   (1 << 0)        /* host is ready for data r/w */
+
+       /* SerialState notification -- CDC 1.1 section 6.3.5 (OUTPUT) */
+       u16                             serial_state;
+#define ACM_CTRL_OVERRUN       (1 << 6)
+#define ACM_CTRL_PARITY                (1 << 5)
+#define ACM_CTRL_FRAMING       (1 << 4)
+#define ACM_CTRL_RI            (1 << 3)
+#define ACM_CTRL_BRK           (1 << 2)
+#define ACM_CTRL_DSR           (1 << 1)
+#define ACM_CTRL_DCD           (1 << 0)
 };
 
 static inline struct f_acm *func_to_acm(struct usb_function *f)
@@ -66,12 +85,17 @@ static inline struct f_acm *func_to_acm(struct usb_function *f)
        return container_of(f, struct f_acm, port.func);
 }
 
+static inline struct f_acm *port_to_acm(struct gserial *p)
+{
+       return container_of(p, struct f_acm, port);
+}
+
 /*-------------------------------------------------------------------------*/
 
 /* notification endpoint uses smallish and infrequent fixed-size messages */
 
 #define GS_LOG2_NOTIFY_INTERVAL                5       /* 1 << 5 == 32 msec */
-#define GS_NOTIFY_MAXPACKET            8
+#define GS_NOTIFY_MAXPACKET            10      /* notification + 2 bytes */
 
 /* interface and class descriptors: */
 
@@ -117,7 +141,7 @@ static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
        .bLength =              sizeof(acm_descriptor),
        .bDescriptorType =      USB_DT_CS_INTERFACE,
        .bDescriptorSubType =   USB_CDC_ACM_TYPE,
-       .bmCapabilities =       (1 << 1),
+       .bmCapabilities =       USB_CDC_CAP_LINE,
 };
 
 static struct usb_cdc_union_desc acm_union_desc __initdata = {
@@ -277,6 +301,11 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 
        /* composite driver infrastructure handles everything except
         * CDC class messages; interface activation uses set_alt().
+        *
+        * Note CDC spec table 4 lists the ACM request profile.  It requires
+        * encapsulated command support ... we don't handle any, and respond
+        * to them by stalling.  Options include get/set/clear comm features
+        * (not that useful) and SEND_BREAK.
         */
        switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
 
@@ -312,7 +341,7 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
                value = 0;
 
                /* FIXME we should not allow data to flow until the
-                * host sets the RS232_DTR bit; and when it clears
+                * host sets the ACM_CTRL_DTR bit; and when it clears
                 * that bit, we should return to that no-flow state.
                 */
                acm->port_handshake_bits = w_value;
@@ -350,9 +379,6 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
        /* we know alt == 0, so this is an activation or a reset */
 
        if (intf == acm->ctrl_id) {
-               /* REVISIT this may need more work when we start to
-                * send notifications ...
-                */
                if (acm->notify->driver_data) {
                        VDBG(cdev, "reset acm control interface %d\n", intf);
                        usb_ep_disable(acm->notify);
@@ -397,6 +423,128 @@ static void acm_disable(struct usb_function *f)
 
 /*-------------------------------------------------------------------------*/
 
+/**
+ * acm_cdc_notify - issue CDC notification to host
+ * @acm: wraps host to be notified
+ * @type: notification type
+ * @value: Refer to cdc specs, wValue field.
+ * @data: data to be sent
+ * @length: size of data
+ * Context: irqs blocked, acm->lock held, acm_notify_req non-null
+ *
+ * Returns zero on sucess or a negative errno.
+ *
+ * See section 6.3.5 of the CDC 1.1 specification for information
+ * about the only notification we issue:  SerialState change.
+ */
+static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value,
+               void *data, unsigned length)
+{
+       struct usb_ep                   *ep = acm->notify;
+       struct usb_request              *req;
+       struct usb_cdc_notification     *notify;
+       const unsigned                  len = sizeof(*notify) + length;
+       void                            *buf;
+       int                             status;
+
+       req = acm->notify_req;
+       acm->notify_req = NULL;
+       acm->pending = false;
+
+       req->length = len;
+       notify = req->buf;
+       buf = notify + 1;
+
+       notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
+                       | USB_RECIP_INTERFACE;
+       notify->bNotificationType = type;
+       notify->wValue = cpu_to_le16(value);
+       notify->wIndex = cpu_to_le16(acm->ctrl_id);
+       notify->wLength = cpu_to_le16(length);
+       memcpy(buf, data, length);
+
+       status = usb_ep_queue(ep, req, GFP_ATOMIC);
+       if (status < 0) {
+               ERROR(acm->port.func.config->cdev,
+                               "acm ttyGS%d can't notify serial state, %d\n",
+                               acm->port_num, status);
+               acm->notify_req = req;
+       }
+
+       return status;
+}
+
+static int acm_notify_serial_state(struct f_acm *acm)
+{
+       struct usb_composite_dev *cdev = acm->port.func.config->cdev;
+       int                     status;
+
+       spin_lock(&acm->lock);
+       if (acm->notify_req) {
+               DBG(cdev, "acm ttyGS%d serial state %04x\n",
+                               acm->port_num, acm->serial_state);
+               status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
+                               0, &acm->serial_state, sizeof(acm->serial_state));
+       } else {
+               acm->pending = true;
+               status = 0;
+       }
+       spin_unlock(&acm->lock);
+       return status;
+}
+
+static void acm_cdc_notify_complete(struct usb_ep *ep, struct usb_request *req)
+{
+       struct f_acm            *acm = req->context;
+       u8                      doit = false;
+
+       /* on this call path we do NOT hold the port spinlock,
+        * which is why ACM needs its own spinlock
+        */
+       spin_lock(&acm->lock);
+       if (req->status != -ESHUTDOWN)
+               doit = acm->pending;
+       acm->notify_req = req;
+       spin_unlock(&acm->lock);
+
+       if (doit)
+               acm_notify_serial_state(acm);
+}
+
+/* connect == the TTY link is open */
+
+static void acm_connect(struct gserial *port)
+{
+       struct f_acm            *acm = port_to_acm(port);
+
+       acm->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
+       acm_notify_serial_state(acm);
+}
+
+static void acm_disconnect(struct gserial *port)
+{
+       struct f_acm            *acm = port_to_acm(port);
+
+       acm->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
+       acm_notify_serial_state(acm);
+}
+
+static int acm_send_break(struct gserial *port, int duration)
+{
+       struct f_acm            *acm = port_to_acm(port);
+       u16                     state;
+
+       state = acm->serial_state;
+       state &= ~ACM_CTRL_BRK;
+       if (duration)
+               state |= ACM_CTRL_BRK;
+
+       acm->serial_state = state;
+       return acm_notify_serial_state(acm);
+}
+
+/*-------------------------------------------------------------------------*/
+
 /* ACM function driver setup/binding */
 static int __init
 acm_bind(struct usb_configuration *c, struct usb_function *f)
@@ -445,8 +593,20 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
        acm->notify = ep;
        ep->driver_data = cdev; /* claim */
 
+       /* allocate notification */
+       acm->notify_req = gs_alloc_req(ep,
+                       sizeof(struct usb_cdc_notification) + 2,
+                       GFP_KERNEL);
+       if (!acm->notify_req)
+               goto fail;
+
+       acm->notify_req->complete = acm_cdc_notify_complete;
+       acm->notify_req->context = acm;
+
        /* copy descriptors, and track endpoint copies */
        f->descriptors = usb_copy_descriptors(acm_fs_function);
+       if (!f->descriptors)
+               goto fail;
 
        acm->fs.in = usb_find_endpoint(acm_fs_function,
                        f->descriptors, &acm_fs_in_desc);
@@ -478,8 +638,6 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
                                f->hs_descriptors, &acm_hs_notify_desc);
        }
 
-       /* FIXME provide a callback for triggering notifications */
-
        DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
                        acm->port_num,
                        gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@@ -488,6 +646,9 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
+       if (acm->notify_req)
+               gs_free_req(acm->notify, acm->notify_req);
+
        /* we might as well release our claims on endpoints */
        if (acm->notify)
                acm->notify->driver_data = NULL;
@@ -504,10 +665,13 @@ fail:
 static void
 acm_unbind(struct usb_configuration *c, struct usb_function *f)
 {
+       struct f_acm            *acm = func_to_acm(f);
+
        if (gadget_is_dualspeed(c->cdev->gadget))
                usb_free_descriptors(f->hs_descriptors);
        usb_free_descriptors(f->descriptors);
-       kfree(func_to_acm(f));
+       gs_free_req(acm->notify, acm->notify_req);
+       kfree(acm);
 }
 
 /* Some controllers can't support CDC ACM ... */
@@ -571,8 +735,14 @@ int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
        if (!acm)
                return -ENOMEM;
 
+       spin_lock_init(&acm->lock);
+
        acm->port_num = port_num;
 
+       acm->port.connect = acm_connect;
+       acm->port.disconnect = acm_disconnect;
+       acm->port.send_break = acm_send_break;
+
        acm->port.func.name = "acm";
        acm->port.func.strings = acm_strings;
        /* descriptors are per-instance copies */
index 0822e9d7693a67567f043ef9fb3674e4b107960a..a2b5c092bda039bdf0c1cd70b7d4bc2d6445cc99 100644 (file)
@@ -63,9 +63,7 @@ struct f_ecm {
 
        char                            ethaddr[14];
 
-       struct usb_descriptor_header    **fs_function;
        struct ecm_ep_descs             fs;
-       struct usb_descriptor_header    **hs_function;
        struct ecm_ep_descs             hs;
 
        struct usb_ep                   *notify;
index 61652f0f13fd93c05acecfd9725f54a1c0231d09..659b3d9671c4fe3f0f31220cb4b3bde514d88d2b 100644 (file)
@@ -85,9 +85,7 @@ struct f_rndis {
        u8                              ethaddr[ETH_ALEN];
        int                             config;
 
-       struct usb_descriptor_header    **fs_function;
        struct rndis_ep_descs           fs;
-       struct usb_descriptor_header    **hs_function;
        struct rndis_ep_descs           hs;
 
        struct usb_ep                   *notify;
index 1b6bde9aaed561e6d28e435567d38ef155187459..fe5674db344bf862fccd98b91d1afc16a4579bec 100644 (file)
@@ -36,9 +36,7 @@ struct f_gser {
        u8                              data_id;
        u8                              port_num;
 
-       struct usb_descriptor_header    **fs_function;
        struct gser_descs               fs;
-       struct usb_descriptor_header    **hs_function;
        struct gser_descs               hs;
 };
 
index afeab9a0523f86ea5ff29eecea34947721b40eec..acb8d233aa1d24a02a5acc855a040755b809013b 100644 (file)
@@ -66,9 +66,7 @@ struct f_gether {
 
        char                            ethaddr[14];
 
-       struct usb_descriptor_header    **fs_function;
        struct geth_descs               fs;
-       struct usb_descriptor_header    **hs_function;
        struct geth_descs               hs;
 };
 
index 5246e8fef2b276b28d5e64095fa77493eae91232..17d9905101b75a9ebc082b92c9fe00ade4c34f84 100644 (file)
  * Some are available on 2.4 kernels; several are available, but not
  * yet pushed in the 2.6 mainline tree.
  */
+
+#ifndef __GADGET_CHIPS_H
+#define __GADGET_CHIPS_H
+
 #ifdef CONFIG_USB_GADGET_NET2280
 #define        gadget_is_net2280(g)    !strcmp("net2280", (g)->name)
 #else
@@ -237,3 +241,5 @@ static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
        /* Everything else is *presumably* fine ... */
        return true;
 }
+
+#endif /* __GADGET_CHIPS_H */
index 376e80c07530eba7093de756fdfa107a1e1348ef..574c53831a05fd17afd6062633aaab4843609e5f 100644 (file)
@@ -54,6 +54,7 @@
 
 #include <mach/dma.h>
 #include <mach/usb.h>
+#include <mach/control.h>
 
 #include "omap_udc.h"
 
@@ -2310,10 +2311,10 @@ static int proc_otg_show(struct seq_file *s)
        u32             trans;
        char            *ctrl_name;
 
-       tmp = OTG_REV_REG;
+       tmp = omap_readl(OTG_REV);
        if (cpu_is_omap24xx()) {
                ctrl_name = "control_devconf";
-               trans = CONTROL_DEVCONF_REG;
+               trans = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
        } else {
                ctrl_name = "tranceiver_ctrl";
                trans = omap_readw(USB_TRANSCEIVER_CTRL);
index abf9505d3a75e1a5b263d08b742ad33b108d0fa1..53d59287f2bc8fcd0599e3bd597d2bcd26280ece 100644 (file)
  * is managed in userspace ... OBEX, PTP, and MTP have been mentioned.
  */
 
+#define PREFIX "ttyGS"
+
 /*
  * gserial is the lifecycle interface, used by USB functions
  * gs_port is the I/O nexus, used by the tty driver
  * tty_struct links to the tty/filesystem framework
  *
  * gserial <---> gs_port ... links will be null when the USB link is
- * inactive; managed by gserial_{connect,disconnect}().
+ * inactive; managed by gserial_{connect,disconnect}().  each gserial
+ * instance can wrap its own USB control protocol.
  *     gserial->ioport == usb_ep->driver_data ... gs_port
  *     gs_port->port_usb ... gserial
  *
@@ -100,6 +103,8 @@ struct gs_port {
        wait_queue_head_t       close_wait;     /* wait for last close */
 
        struct list_head        read_pool;
+       struct list_head        read_queue;
+       unsigned                n_read;
        struct tasklet_struct   push;
 
        struct list_head        write_pool;
@@ -177,7 +182,7 @@ static void gs_buf_clear(struct gs_buf *gb)
 /*
  * gs_buf_data_avail
  *
- * Return the number of bytes of data available in the circular
+ * Return the number of bytes of data written into the circular
  * buffer.
  */
 static unsigned gs_buf_data_avail(struct gs_buf *gb)
@@ -278,7 +283,7 @@ gs_buf_get(struct gs_buf *gb, char *buf, unsigned count)
  * Allocate a usb_request and its buffer.  Returns a pointer to the
  * usb_request or NULL if there is an error.
  */
-static struct usb_request *
+struct usb_request *
 gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
 {
        struct usb_request *req;
@@ -302,7 +307,7 @@ gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
  *
  * Free a usb_request and its buffer.
  */
-static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
+void gs_free_req(struct usb_ep *ep, struct usb_request *req)
 {
        kfree(req->buf);
        usb_ep_free_request(ep, req);
@@ -367,11 +372,9 @@ __acquires(&port->port_lock)
                req->length = len;
                list_del(&req->list);
 
-#ifdef VERBOSE_DEBUG
-               pr_debug("%s: %s, len=%d, 0x%02x 0x%02x 0x%02x ...\n",
-                               __func__, in->name, len, *((u8 *)req->buf),
+               pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
+                               port->port_num, len, *((u8 *)req->buf),
                                *((u8 *)req->buf+1), *((u8 *)req->buf+2));
-#endif
 
                /* Drop lock while we call out of driver; completions
                 * could be issued while we do so.  Disconnection may
@@ -401,56 +404,6 @@ __acquires(&port->port_lock)
        return status;
 }
 
-static void gs_rx_push(unsigned long _port)
-{
-       struct gs_port          *port = (void *)_port;
-       struct tty_struct       *tty = port->port_tty;
-
-       /* With low_latency, tty_flip_buffer_push() doesn't put its
-        * real work through a workqueue, so the ldisc has a better
-        * chance to keep up with peak USB data rates.
-        */
-       if (tty) {
-               tty_flip_buffer_push(tty);
-               wake_up_interruptible(&tty->read_wait);
-       }
-}
-
-/*
- * gs_recv_packet
- *
- * Called for each USB packet received.  Reads the packet
- * header and stuffs the data in the appropriate tty buffer.
- * Returns 0 if successful, or a negative error number.
- *
- * Called during USB completion routine, on interrupt time.
- * With port_lock.
- */
-static int gs_recv_packet(struct gs_port *port, char *packet, unsigned size)
-{
-       unsigned                len;
-       struct tty_struct       *tty;
-
-       /* I/O completions can continue for a while after close(), until the
-        * request queue empties.  Just discard any data we receive, until
-        * something reopens this TTY ... as if there were no HW flow control.
-        */
-       tty = port->port_tty;
-       if (tty == NULL) {
-               pr_vdebug("%s: ttyGS%d, after close\n",
-                               __func__, port->port_num);
-               return -EIO;
-       }
-
-       len = tty_insert_flip_string(tty, packet, size);
-       if (len > 0)
-               tasklet_schedule(&port->push);
-       if (len < size)
-               pr_debug("%s: ttyGS%d, drop %d bytes\n",
-                               __func__, port->port_num, size - len);
-       return 0;
-}
-
 /*
  * Context: caller owns port_lock, and port_usb is set
  */
@@ -469,9 +422,9 @@ __acquires(&port->port_lock)
                int                     status;
                struct tty_struct       *tty;
 
-               /* no more rx if closed or throttled */
+               /* no more rx if closed */
                tty = port->port_tty;
-               if (!tty || test_bit(TTY_THROTTLED, &tty->flags))
+               if (!tty)
                        break;
 
                req = list_entry(pool->next, struct usb_request, list);
@@ -500,36 +453,134 @@ __acquires(&port->port_lock)
        return started;
 }
 
-static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
+/*
+ * RX tasklet takes data out of the RX queue and hands it up to the TTY
+ * layer until it refuses to take any more data (or is throttled back).
+ * Then it issues reads for any further data.
+ *
+ * If the RX queue becomes full enough that no usb_request is queued,
+ * the OUT endpoint may begin NAKing as soon as its FIFO fills up.
+ * So QUEUE_SIZE packets plus however many the FIFO holds (usually two)
+ * can be buffered before the TTY layer's buffers (currently 64 KB).
+ */
+static void gs_rx_push(unsigned long _port)
 {
-       int             status;
-       struct gs_port  *port = ep->driver_data;
+       struct gs_port          *port = (void *)_port;
+       struct tty_struct       *tty;
+       struct list_head        *queue = &port->read_queue;
+       bool                    disconnect = false;
+       bool                    do_push = false;
 
-       spin_lock(&port->port_lock);
-       list_add(&req->list, &port->read_pool);
+       /* hand any queued data to the tty */
+       spin_lock_irq(&port->port_lock);
+       tty = port->port_tty;
+       while (!list_empty(queue)) {
+               struct usb_request      *req;
 
-       switch (req->status) {
-       case 0:
-               /* normal completion */
-               status = gs_recv_packet(port, req->buf, req->actual);
-               if (status && status != -EIO)
-                       pr_debug("%s: %s %s err %d\n",
-                               __func__, "recv", ep->name, status);
-               gs_start_rx(port);
-               break;
+               req = list_first_entry(queue, struct usb_request, list);
 
-       case -ESHUTDOWN:
-               /* disconnect */
-               pr_vdebug("%s: %s shutdown\n", __func__, ep->name);
-               break;
+               /* discard data if tty was closed */
+               if (!tty)
+                       goto recycle;
 
-       default:
-               /* presumably a transient fault */
-               pr_warning("%s: unexpected %s status %d\n",
-                               __func__, ep->name, req->status);
-               gs_start_rx(port);
-               break;
+               /* leave data queued if tty was rx throttled */
+               if (test_bit(TTY_THROTTLED, &tty->flags))
+                       break;
+
+               switch (req->status) {
+               case -ESHUTDOWN:
+                       disconnect = true;
+                       pr_vdebug(PREFIX "%d: shutdown\n", port->port_num);
+                       break;
+
+               default:
+                       /* presumably a transient fault */
+                       pr_warning(PREFIX "%d: unexpected RX status %d\n",
+                                       port->port_num, req->status);
+                       /* FALLTHROUGH */
+               case 0:
+                       /* normal completion */
+                       break;
+               }
+
+               /* push data to (open) tty */
+               if (req->actual) {
+                       char            *packet = req->buf;
+                       unsigned        size = req->actual;
+                       unsigned        n;
+                       int             count;
+
+                       /* we may have pushed part of this packet already... */
+                       n = port->n_read;
+                       if (n) {
+                               packet += n;
+                               size -= n;
+                       }
+
+                       count = tty_insert_flip_string(tty, packet, size);
+                       if (count)
+                               do_push = true;
+                       if (count != size) {
+                               /* stop pushing; TTY layer can't handle more */
+                               port->n_read += count;
+                               pr_vdebug(PREFIX "%d: rx block %d/%d\n",
+                                               port->port_num,
+                                               count, req->actual);
+                               break;
+                       }
+                       port->n_read = 0;
+               }
+recycle:
+               list_move(&req->list, &port->read_pool);
        }
+
+       /* Push from tty to ldisc; this is immediate with low_latency, and
+        * may trigger callbacks to this driver ... so drop the spinlock.
+        */
+       if (tty && do_push) {
+               spin_unlock_irq(&port->port_lock);
+               tty_flip_buffer_push(tty);
+               wake_up_interruptible(&tty->read_wait);
+               spin_lock_irq(&port->port_lock);
+
+               /* tty may have been closed */
+               tty = port->port_tty;
+       }
+
+
+       /* We want our data queue to become empty ASAP, keeping data
+        * in the tty and ldisc (not here).  If we couldn't push any
+        * this time around, there may be trouble unless there's an
+        * implicit tty_unthrottle() call on its way...
+        *
+        * REVISIT we should probably add a timer to keep the tasklet
+        * from starving ... but it's not clear that case ever happens.
+        */
+       if (!list_empty(queue) && tty) {
+               if (!test_bit(TTY_THROTTLED, &tty->flags)) {
+                       if (do_push)
+                               tasklet_schedule(&port->push);
+                       else
+                               pr_warning(PREFIX "%d: RX not scheduled?\n",
+                                       port->port_num);
+               }
+       }
+
+       /* If we're still connected, refill the USB RX queue. */
+       if (!disconnect && port->port_usb)
+               gs_start_rx(port);
+
+       spin_unlock_irq(&port->port_lock);
+}
+
+static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
+{
+       struct gs_port  *port = ep->driver_data;
+
+       /* Queue all received data until the tty layer is ready for it. */
+       spin_lock(&port->port_lock);
+       list_add_tail(&req->list, &port->read_queue);
+       tasklet_schedule(&port->push);
        spin_unlock(&port->port_lock);
 }
 
@@ -625,6 +676,7 @@ static int gs_start_io(struct gs_port *port)
        }
 
        /* queue read requests */
+       port->n_read = 0;
        started = gs_start_rx(port);
 
        /* unblock any pending writes into our circular buffer */
@@ -633,9 +685,10 @@ static int gs_start_io(struct gs_port *port)
        } else {
                gs_free_requests(ep, head);
                gs_free_requests(port->port_usb->in, &port->write_pool);
+               status = -EIO;
        }
 
-       return started ? 0 : status;
+       return status;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -736,10 +789,13 @@ static int gs_open(struct tty_struct *tty, struct file *file)
 
        /* if connected, start the I/O stream */
        if (port->port_usb) {
+               struct gserial  *gser = port->port_usb;
+
                pr_debug("gs_open: start ttyGS%d\n", port->port_num);
                gs_start_io(port);
 
-               /* REVISIT for ACM, issue "network connected" event */
+               if (gser->connect)
+                       gser->connect(gser);
        }
 
        pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file);
@@ -766,6 +822,7 @@ static int gs_writes_finished(struct gs_port *p)
 static void gs_close(struct tty_struct *tty, struct file *file)
 {
        struct gs_port *port = tty->driver_data;
+       struct gserial  *gser;
 
        spin_lock_irq(&port->port_lock);
 
@@ -785,32 +842,31 @@ static void gs_close(struct tty_struct *tty, struct file *file)
        port->openclose = true;
        port->open_count = 0;
 
-       if (port->port_usb)
-               /* REVISIT for ACM, issue "network disconnected" event */;
+       gser = port->port_usb;
+       if (gser && gser->disconnect)
+               gser->disconnect(gser);
 
        /* wait for circular write buffer to drain, disconnect, or at
         * most GS_CLOSE_TIMEOUT seconds; then discard the rest
         */
-       if (gs_buf_data_avail(&port->port_write_buf) > 0
-                       && port->port_usb) {
+       if (gs_buf_data_avail(&port->port_write_buf) > 0 && gser) {
                spin_unlock_irq(&port->port_lock);
                wait_event_interruptible_timeout(port->drain_wait,
                                        gs_writes_finished(port),
                                        GS_CLOSE_TIMEOUT * HZ);
                spin_lock_irq(&port->port_lock);
+               gser = port->port_usb;
        }
 
        /* Iff we're disconnected, there can be no I/O in flight so it's
         * ok to free the circular buffer; else just scrub it.  And don't
         * let the push tasklet fire again until we're re-opened.
         */
-       if (port->port_usb == NULL)
+       if (gser == NULL)
                gs_buf_free(&port->port_write_buf);
        else
                gs_buf_clear(&port->port_write_buf);
 
-       tasklet_kill(&port->push);
-
        tty->driver_data = NULL;
        port->port_tty = NULL;
 
@@ -911,15 +967,35 @@ static void gs_unthrottle(struct tty_struct *tty)
 {
        struct gs_port          *port = tty->driver_data;
        unsigned long           flags;
-       unsigned                started = 0;
 
        spin_lock_irqsave(&port->port_lock, flags);
-       if (port->port_usb)
-               started = gs_start_rx(port);
+       if (port->port_usb) {
+               /* Kickstart read queue processing.  We don't do xon/xoff,
+                * rts/cts, or other handshaking with the host, but if the
+                * read queue backs up enough we'll be NAKing OUT packets.
+                */
+               tasklet_schedule(&port->push);
+               pr_vdebug(PREFIX "%d: unthrottle\n", port->port_num);
+       }
        spin_unlock_irqrestore(&port->port_lock, flags);
+}
+
+static int gs_break_ctl(struct tty_struct *tty, int duration)
+{
+       struct gs_port  *port = tty->driver_data;
+       int             status = 0;
+       struct gserial  *gser;
+
+       pr_vdebug("gs_break_ctl: ttyGS%d, send break (%d) \n",
+                       port->port_num, duration);
 
-       pr_vdebug("gs_unthrottle: ttyGS%d, %d packets\n",
-                       port->port_num, started);
+       spin_lock_irq(&port->port_lock);
+       gser = port->port_usb;
+       if (gser && gser->send_break)
+               status = gser->send_break(gser, duration);
+       spin_unlock_irq(&port->port_lock);
+
+       return status;
 }
 
 static const struct tty_operations gs_tty_ops = {
@@ -931,6 +1007,7 @@ static const struct tty_operations gs_tty_ops = {
        .write_room =           gs_write_room,
        .chars_in_buffer =      gs_chars_in_buffer,
        .unthrottle =           gs_unthrottle,
+       .break_ctl =            gs_break_ctl,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -953,6 +1030,7 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
        tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
 
        INIT_LIST_HEAD(&port->read_pool);
+       INIT_LIST_HEAD(&port->read_queue);
        INIT_LIST_HEAD(&port->write_pool);
 
        port->port_num = port_num;
@@ -997,7 +1075,7 @@ int __init gserial_setup(struct usb_gadget *g, unsigned count)
 
        gs_tty_driver->owner = THIS_MODULE;
        gs_tty_driver->driver_name = "g_serial";
-       gs_tty_driver->name = "ttyGS";
+       gs_tty_driver->name = PREFIX;
        /* uses dynamically assigned dev_t values */
 
        gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
@@ -1104,6 +1182,8 @@ void gserial_cleanup(void)
                ports[i].port = NULL;
                mutex_unlock(&ports[i].lock);
 
+               tasklet_kill(&port->push);
+
                /* wait for old opens to finish */
                wait_event(port->close_wait, gs_closed(port));
 
@@ -1175,14 +1255,17 @@ int gserial_connect(struct gserial *gser, u8 port_num)
 
        /* REVISIT if waiting on "carrier detect", signal. */
 
-       /* REVISIT for ACM, issue "network connection" status notification:
-        * connected if open_count, else disconnected.
+       /* if it's already open, start I/O ... and notify the serial
+        * protocol about open/close status (connect/disconnect).
         */
-
-       /* if it's already open, start I/O */
        if (port->open_count) {
                pr_debug("gserial_connect: start ttyGS%d\n", port->port_num);
                gs_start_io(port);
+               if (gser->connect)
+                       gser->connect(gser);
+       } else {
+               if (gser->disconnect)
+                       gser->disconnect(gser);
        }
 
        spin_unlock_irqrestore(&port->port_lock, flags);
@@ -1241,6 +1324,7 @@ void gserial_disconnect(struct gserial *gser)
        if (port->open_count == 0 && !port->openclose)
                gs_buf_free(&port->port_write_buf);
        gs_free_requests(gser->out, &port->read_pool);
+       gs_free_requests(gser->out, &port->read_queue);
        gs_free_requests(gser->in, &port->write_pool);
        spin_unlock_irqrestore(&port->port_lock, flags);
 }
index 7b561138f90e06916080d406f7cfab1d655905c3..af3910d01aea65f7b92e16e7e10770b0ccd74828 100644 (file)
@@ -23,8 +23,7 @@
  * style I/O using the USB peripheral endpoints listed here, including
  * hookups to sysfs and /dev for each logical "tty" device.
  *
- * REVISIT need TTY --> USB event flow too, so ACM can report open/close
- * as carrier detect events.  Model after ECM.  There's more ACM state too.
+ * REVISIT at least ACM could support tiocmget() if needed.
  *
  * REVISIT someday, allow multiplexing several TTYs over these endpoints.
  */
@@ -41,8 +40,17 @@ struct gserial {
 
        /* REVISIT avoid this CDC-ACM support harder ... */
        struct usb_cdc_line_coding port_line_coding;    /* 9600-8-N-1 etc */
+
+       /* notification callbacks */
+       void (*connect)(struct gserial *p);
+       void (*disconnect)(struct gserial *p);
+       int (*send_break)(struct gserial *p, int duration);
 };
 
+/* utilities to allocate/free request and buffer */
+struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags);
+void gs_free_req(struct usb_ep *, struct usb_request *req);
+
 /* port setup/teardown is handled by gadget driver */
 int gserial_setup(struct usb_gadget *g, unsigned n_ports);
 void gserial_cleanup(void);
index c858f2adb929904631746151469696c73b22cd22..d22a84f86a33755a3749f275cd49e031ee14ac06 100644 (file)
@@ -126,9 +126,8 @@ static void isp1760_writel(const unsigned int val, __u32 __iomem *regs)
  * doesn't quite work because some people have to enforce 32-bit access
  */
 static void priv_read_copy(struct isp1760_hcd *priv, u32 *src,
-               __u32 __iomem *dst, u32 offset, u32 len)
+               __u32 __iomem *dst, u32 len)
 {
-       struct usb_hcd *hcd = priv_to_hcd(priv);
        u32 val;
        u8 *buff8;
 
@@ -136,11 +135,6 @@ static void priv_read_copy(struct isp1760_hcd *priv, u32 *src,
                printk(KERN_ERR "ERROR: buffer: %p len: %d\n", src, len);
                return;
        }
-       isp1760_writel(offset,  hcd->regs + HC_MEMORY_REG);
-       /* XXX
-        * 90nsec delay, the spec says something how this could be avoided.
-        */
-       mdelay(1);
 
        while (len >= 4) {
                *src = __raw_readl(dst);
@@ -987,8 +981,20 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
                        printk(KERN_ERR "qh is 0\n");
                        continue;
                }
-               priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs,
-                               atl_regs, sizeof(ptd));
+               isp1760_writel(atl_regs + ISP_BANK(0), usb_hcd->regs +
+                               HC_MEMORY_REG);
+               isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
+                               HC_MEMORY_REG);
+               /*
+                * write bank1 address twice to ensure the 90ns delay (time
+                * between BANK0 write and the priv_read_copy() call is at
+                * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns)
+                */
+               isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
+                               HC_MEMORY_REG);
+
+               priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs +
+                               ISP_BANK(0), sizeof(ptd));
 
                dw1 = le32_to_cpu(ptd.dw1);
                dw2 = le32_to_cpu(ptd.dw2);
@@ -1091,7 +1097,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
                        case IN_PID:
                                priv_read_copy(priv,
                                        priv->atl_ints[queue_entry].data_buffer,
-                                       usb_hcd->regs + payload, payload,
+                                       usb_hcd->regs + payload + ISP_BANK(1),
                                        length);
 
                        case OUT_PID:
@@ -1122,11 +1128,11 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
                } else if (usb_pipebulk(urb->pipe) && (length < qtd->length)) {
                        /* short BULK received */
 
-                       printk(KERN_ERR "short bulk, %d instead %zu\n", length,
-                                       qtd->length);
                        if (urb->transfer_flags & URB_SHORT_NOT_OK) {
                                urb->status = -EREMOTEIO;
-                               printk(KERN_ERR "not okey\n");
+                               isp1760_dbg(priv, "short bulk, %d instead %zu "
+                                       "with URB_SHORT_NOT_OK flag.\n",
+                                       length, qtd->length);
                        }
 
                        if (urb->status == -EINPROGRESS)
@@ -1206,8 +1212,20 @@ static void do_intl_int(struct usb_hcd *usb_hcd)
                        continue;
                }
 
-               priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + int_regs,
-                               int_regs, sizeof(ptd));
+               isp1760_writel(int_regs + ISP_BANK(0), usb_hcd->regs +
+                               HC_MEMORY_REG);
+               isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
+                               HC_MEMORY_REG);
+               /*
+                * write bank1 address twice to ensure the 90ns delay (time
+                * between BANK0 write and the priv_read_copy() call is at
+                * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns)
+                */
+               isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
+                               HC_MEMORY_REG);
+
+               priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + int_regs +
+                               ISP_BANK(0), sizeof(ptd));
                dw1 = le32_to_cpu(ptd.dw1);
                dw3 = le32_to_cpu(ptd.dw3);
                check_int_err_status(le32_to_cpu(ptd.dw4));
@@ -1242,7 +1260,7 @@ static void do_intl_int(struct usb_hcd *usb_hcd)
                        case IN_PID:
                                priv_read_copy(priv,
                                        priv->int_ints[queue_entry].data_buffer,
-                                       usb_hcd->regs + payload , payload,
+                                       usb_hcd->regs + payload + ISP_BANK(1),
                                        length);
                        case OUT_PID:
 
@@ -1615,8 +1633,7 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
                return -EPIPE;
        }
 
-       isp1760_prepare_enqueue(priv, urb, &qtd_list, mem_flags, pe);
-       return 0;
+       return isp1760_prepare_enqueue(priv, urb, &qtd_list, mem_flags, pe);
 }
 
 static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
index 6473dd86993cb8d19b288dbdcae926e723c5f9c9..4377277667d9bfed2274518d9954ae9a0b2c9997 100644 (file)
@@ -54,6 +54,8 @@ void deinit_kmem_cache(void);
 #define BUFFER_MAP             0x7
 
 #define HC_MEMORY_REG          0x33c
+#define ISP_BANK(x)            ((x) << 16)
+
 #define HC_PORT1_CTRL          0x374
 #define PORT1_POWER            (3 << 3)
 #define PORT1_INIT1            (1 << 7)
@@ -119,6 +121,9 @@ struct inter_packet_info {
 typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh,
                struct isp1760_qtd *qtd);
 
+#define isp1760_dbg(priv, fmt, args...) \
+       dev_dbg(priv_to_hcd(priv)->self.controller, fmt, ##args)
+
 #define isp1760_info(priv, fmt, args...) \
        dev_info(priv_to_hcd(priv)->self.controller, fmt, ##args)
 
index 26bc47941d0132f46badea48da3855daf7dedfff..89901962cbfd821bc454353f61ed1e4e66ecf8db 100644 (file)
@@ -86,6 +86,21 @@ static void ohci_stop (struct usb_hcd *hcd);
 static int ohci_restart (struct ohci_hcd *ohci);
 #endif
 
+#ifdef CONFIG_PCI
+static void quirk_amd_pll(int state);
+static void amd_iso_dev_put(void);
+#else
+static inline void quirk_amd_pll(int state)
+{
+       return;
+}
+static inline void amd_iso_dev_put(void)
+{
+       return;
+}
+#endif
+
+
 #include "ohci-hub.c"
 #include "ohci-dbg.c"
 #include "ohci-mem.c"
@@ -483,6 +498,9 @@ static int ohci_init (struct ohci_hcd *ohci)
        int ret;
        struct usb_hcd *hcd = ohci_to_hcd(ohci);
 
+       if (distrust_firmware)
+               ohci->flags |= OHCI_QUIRK_HUB_POWER;
+
        disable (ohci);
        ohci->regs = hcd->regs;
 
@@ -689,7 +707,8 @@ retry:
                temp |= RH_A_NOCP;
                temp &= ~(RH_A_POTPGT | RH_A_NPS);
                ohci_writel (ohci, temp, &ohci->regs->roothub.a);
-       } else if ((ohci->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
+       } else if ((ohci->flags & OHCI_QUIRK_AMD756) ||
+                       (ohci->flags & OHCI_QUIRK_HUB_POWER)) {
                /* hub power always on; required for AMD-756 and some
                 * Mac platforms.  ganged overcurrent reporting, if any.
                 */
@@ -882,6 +901,8 @@ static void ohci_stop (struct usb_hcd *hcd)
 
        if (quirk_zfmicro(ohci))
                del_timer(&ohci->unlink_watchdog);
+       if (quirk_amdiso(ohci))
+               amd_iso_dev_put();
 
        remove_debug_files (ohci);
        ohci_mem_cleanup (ohci);
index b56739221d11f27d6d6e1b8d04c833fe56bdbd6c..439beb784f3e1eb42495d4a323288a56d5eea02d 100644 (file)
@@ -483,6 +483,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
                length++;
        }
 
+       /* Some broken controllers never turn off RHCS in the interrupt
+        * status register.  For their sake we won't re-enable RHSC
+        * interrupts if the flag is already set.
+        */
+       if (ohci_readl(ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC)
+               changed = 1;
+
        /* look at each port */
        for (i = 0; i < ohci->num_ports; i++) {
                u32     status = roothub_portstatus (ohci, i);
@@ -572,8 +579,6 @@ static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
        return 0;
 }
 
-static void start_hnp(struct ohci_hcd *ohci);
-
 #else
 
 #define        ohci_start_port_reset           NULL
@@ -760,7 +765,7 @@ static int ohci_hub_control (
 #ifdef CONFIG_USB_OTG
                        if (hcd->self.otg_port == (wIndex + 1)
                                        && hcd->self.b_hnp_enable)
-                               start_hnp(ohci);
+                               ohci->start_hnp(ohci);
                        else
 #endif
                        ohci_writel (ohci, RH_PS_PSS,
index 94dfca02f7e169228197c0a9ebf6b3cd970fade1..3d532b709670c9386959f1a8c84a327875790d10 100644 (file)
@@ -225,6 +225,7 @@ static int ohci_omap_init(struct usb_hcd *hcd)
                        dev_err(hcd->self.controller, "can't find transceiver\n");
                        return -ENODEV;
                }
+               ohci->start_hnp = start_hnp;
        }
 #endif
 
@@ -260,7 +261,7 @@ static int ohci_omap_init(struct usb_hcd *hcd)
                        omap_cfg_reg(W4_USB_HIGHZ);
                }
                ohci_writel(ohci, rh, &ohci->regs->roothub.a);
-               distrust_firmware = 0;
+               ohci->flags &= ~OHCI_QUIRK_HUB_POWER;
        } else if (machine_is_nokia770()) {
                /* We require a self-powered hub, which should have
                 * plenty of power. */
index 4696cc912e16203540a5185568a27e02bb7c15e2..083e8df0a817f83b925ac397f5e90cb43b8af1d2 100644 (file)
 #error "This file is PCI bus glue.  CONFIG_PCI must be defined."
 #endif
 
+#include <linux/pci.h>
+#include <linux/io.h>
+
+
+/* constants used to work around PM-related transfer
+ * glitches in some AMD 700 series southbridges
+ */
+#define AB_REG_BAR     0xf0
+#define AB_INDX(addr)  ((addr) + 0x00)
+#define AB_DATA(addr)  ((addr) + 0x04)
+#define AX_INDXC       0X30
+#define AX_DATAC       0x34
+
+#define NB_PCIE_INDX_ADDR      0xe0
+#define NB_PCIE_INDX_DATA      0xe4
+#define PCIE_P_CNTL            0x10040
+#define BIF_NB                 0x10002
+
+static struct pci_dev *amd_smbus_dev;
+static struct pci_dev *amd_hb_dev;
+static int amd_ohci_iso_count;
+
 /*-------------------------------------------------------------------------*/
 
 static int broken_suspend(struct usb_hcd *hcd)
@@ -143,6 +165,103 @@ static int ohci_quirk_nec(struct usb_hcd *hcd)
        return 0;
 }
 
+static int ohci_quirk_amd700(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       u8 rev = 0;
+
+       if (!amd_smbus_dev)
+               amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
+                               PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
+       if (!amd_smbus_dev)
+               return 0;
+
+       pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
+       if ((rev > 0x3b) || (rev < 0x30)) {
+               pci_dev_put(amd_smbus_dev);
+               amd_smbus_dev = NULL;
+               return 0;
+       }
+
+       amd_ohci_iso_count++;
+
+       if (!amd_hb_dev)
+               amd_hb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9600, NULL);
+
+       ohci->flags |= OHCI_QUIRK_AMD_ISO;
+       ohci_dbg(ohci, "enabled AMD ISO transfers quirk\n");
+
+       return 0;
+}
+
+/*
+ * The hardware normally enables the A-link power management feature, which
+ * lets the system lower the power consumption in idle states.
+ *
+ * Assume the system is configured to have USB 1.1 ISO transfers going
+ * to or from a USB device.  Without this quirk, that stream may stutter
+ * or have breaks occasionally.  For transfers going to speakers, this
+ * makes a very audible mess...
+ *
+ * That audio playback corruption is due to the audio stream getting
+ * interrupted occasionally when the link goes in lower power state
+ * This USB quirk prevents the link going into that lower power state
+ * during audio playback or other ISO operations.
+ */
+static void quirk_amd_pll(int on)
+{
+       u32 addr;
+       u32 val;
+       u32 bit = (on > 0) ? 1 : 0;
+
+       pci_read_config_dword(amd_smbus_dev, AB_REG_BAR, &addr);
+
+       /* BIT names/meanings are NDA-protected, sorry ... */
+
+       outl(AX_INDXC, AB_INDX(addr));
+       outl(0x40, AB_DATA(addr));
+       outl(AX_DATAC, AB_INDX(addr));
+       val = inl(AB_DATA(addr));
+       val &= ~((1 << 3) | (1 << 4) | (1 << 9));
+       val |= (bit << 3) | ((!bit) << 4) | ((!bit) << 9);
+       outl(val, AB_DATA(addr));
+
+       if (amd_hb_dev) {
+               addr = PCIE_P_CNTL;
+               pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr);
+
+               pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val);
+               val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12));
+               val |= bit | (bit << 3) | (bit << 12);
+               val |= ((!bit) << 4) | ((!bit) << 9);
+               pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val);
+
+               addr = BIF_NB;
+               pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr);
+
+               pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val);
+               val &= ~(1 << 8);
+               val |= bit << 8;
+               pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val);
+       }
+}
+
+static void amd_iso_dev_put(void)
+{
+       amd_ohci_iso_count--;
+       if (amd_ohci_iso_count == 0) {
+               if (amd_smbus_dev) {
+                       pci_dev_put(amd_smbus_dev);
+                       amd_smbus_dev = NULL;
+               }
+               if (amd_hb_dev) {
+                       pci_dev_put(amd_hb_dev);
+                       amd_hb_dev = NULL;
+               }
+       }
+
+}
+
 /* List of quirks for OHCI */
 static const struct pci_device_id ohci_pci_quirks[] = {
        {
@@ -181,6 +300,19 @@ static const struct pci_device_id ohci_pci_quirks[] = {
                PCI_DEVICE(PCI_VENDOR_ID_ITE, 0x8152),
                .driver_data = (unsigned long) broken_suspend,
        },
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4397),
+               .driver_data = (unsigned long)ohci_quirk_amd700,
+       },
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4398),
+               .driver_data = (unsigned long)ohci_quirk_amd700,
+       },
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
+               .driver_data = (unsigned long)ohci_quirk_amd700,
+       },
+
        /* FIXME for some of the early AMD 760 southbridges, OHCI
         * won't work at all.  blacklist them.
         */
index 6a9b4c5579536e161b596e824adccf3b81805922..c2d80f80448b2e77690f8f29cc64f3402cd9dd78 100644 (file)
@@ -49,6 +49,9 @@ __acquires(ohci->lock)
        switch (usb_pipetype (urb->pipe)) {
        case PIPE_ISOCHRONOUS:
                ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--;
+               if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0
+                               && quirk_amdiso(ohci))
+                       quirk_amd_pll(1);
                break;
        case PIPE_INTERRUPT:
                ohci_to_hcd(ohci)->self.bandwidth_int_reqs--;
@@ -677,6 +680,9 @@ static void td_submit_urb (
                                data + urb->iso_frame_desc [cnt].offset,
                                urb->iso_frame_desc [cnt].length, urb, cnt);
                }
+               if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0
+                               && quirk_amdiso(ohci))
+                       quirk_amd_pll(0);
                periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0
                        && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0;
                break;
index dc544ddc784962831637e749c4d50420ee24aa0b..faf622eafce7aab820b20ad55bae51b3076579ba 100644 (file)
@@ -371,6 +371,7 @@ struct ohci_hcd {
         * other external transceivers should be software-transparent
         */
        struct otg_transceiver  *transceiver;
+       void (*start_hnp)(struct ohci_hcd *ohci);
 
        /*
         * memory management for queue data structures
@@ -399,6 +400,8 @@ struct ohci_hcd {
 #define        OHCI_QUIRK_ZFMICRO      0x20                    /* Compaq ZFMicro chipset*/
 #define        OHCI_QUIRK_NEC          0x40                    /* lost interrupts */
 #define        OHCI_QUIRK_FRAME_NO     0x80                    /* no big endian frame_no shift */
+#define        OHCI_QUIRK_HUB_POWER    0x100                   /* distrust firmware power/oc setup */
+#define        OHCI_QUIRK_AMD_ISO      0x200                   /* ISO transfers*/
        // there are also chip quirks/bugs in init logic
 
        struct work_struct      nec_work;       /* Worker for NEC quirk */
@@ -426,6 +429,10 @@ static inline int quirk_zfmicro(struct ohci_hcd *ohci)
 {
        return ohci->flags & OHCI_QUIRK_ZFMICRO;
 }
+static inline int quirk_amdiso(struct ohci_hcd *ohci)
+{
+       return ohci->flags & OHCI_QUIRK_AMD_ISO;
+}
 #else
 static inline int quirk_nec(struct ohci_hcd *ohci)
 {
@@ -435,6 +442,10 @@ static inline int quirk_zfmicro(struct ohci_hcd *ohci)
 {
        return 0;
 }
+static inline int quirk_amdiso(struct ohci_hcd *ohci)
+{
+       return 0;
+}
 #endif
 
 /* convert between an hcd pointer and the corresponding ohci_hcd */
index d5f02dddb1203ec31c151401aab80208388d1235..ea7126f99cab33643c6d4e368a6f1b18fc0cd33c 100644 (file)
@@ -964,11 +964,34 @@ static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum)
        disable_irq_nrdy(r8a66597, pipenum);
 }
 
+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,
+                                       int connect)
+{
+       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;
+       if (connect)
+               rh->port |= 1 << USB_PORT_FEAT_CONNECTION;
+       else
+               rh->port &= ~(1 << USB_PORT_FEAT_CONNECTION);
+       rh->port |= 1 << USB_PORT_FEAT_C_CONNECTION;
+
+       r8a66597_root_hub_start_polling(r8a66597);
+}
+
 /* this function must be called with interrupt disabled */
 static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
                                        u16 syssts)
 {
        if (syssts == SE0) {
+               r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
                r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
                return;
        }
@@ -1002,13 +1025,10 @@ static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port)
 {
        struct r8a66597_device *dev = r8a66597->root_hub[port].dev;
 
-       r8a66597->root_hub[port].port &= ~(1 << USB_PORT_FEAT_CONNECTION);
-       r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_C_CONNECTION);
-
        disable_r8a66597_pipe_all(r8a66597, dev);
        free_usb_address(r8a66597, dev);
 
-       r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
+       start_root_hub_sampling(r8a66597, port, 0);
 }
 
 /* this function must be called with interrupt disabled */
@@ -1551,23 +1571,6 @@ 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;
-       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)
 {
        struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
@@ -1594,7 +1597,7 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
                        r8a66597_bclr(r8a66597, ATTCHE, INTENB2);
 
                        /* start usb bus sampling */
-                       start_root_hub_sampling(r8a66597, 1);
+                       start_root_hub_sampling(r8a66597, 1, 1);
                }
                if (mask2 & DTCH) {
                        r8a66597_write(r8a66597, ~DTCH, INTSTS2);
@@ -1609,7 +1612,7 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
                        r8a66597_bclr(r8a66597, ATTCHE, INTENB1);
 
                        /* start usb bus sampling */
-                       start_root_hub_sampling(r8a66597, 0);
+                       start_root_hub_sampling(r8a66597, 0, 1);
                }
                if (mask1 & DTCH) {
                        r8a66597_write(r8a66597, ~DTCH, INTSTS1);
index 001789c9a11a7c6b0e0c531ed4ede55fa77cb361..4ea50e0abcbb1c6abaf958bb34942ea4740ea0d8 100644 (file)
@@ -42,16 +42,6 @@ config USB_ADUTUX
          To compile this driver as a module, choose M here.  The module
          will be called adutux.
 
-config USB_AUERSWALD
-       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.
-
-         To compile this driver as a module, choose M here: the
-         module will be called auerswald.
-
 config USB_RIO500
        tristate "USB Diamond Rio500 support"
        depends on USB
index aba091cb5ec0a99ea40e2eff02067136fd91c838..45b4e12afb085b9552a4ce9b3131319a8c33aa28 100644 (file)
@@ -5,7 +5,6 @@
 
 obj-$(CONFIG_USB_ADUTUX)       += adutux.o
 obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o
-obj-$(CONFIG_USB_AUERSWALD)    += auerswald.o
 obj-$(CONFIG_USB_BERRY_CHARGE) += berry_charge.o
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
 obj-$(CONFIG_USB_CYTHERM)      += cytherm.o
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
deleted file mode 100644 (file)
index d2f61d5..0000000
+++ /dev/null
@@ -1,2152 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerswald.c  --  Auerswald PBX/System Telephone usb driver.
- *
- *      Copyright (C) 2001  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      Very much code of this driver is borrowed from dabusb.c (Deti Fliegl)
- *      and from the USB Skeleton driver (Greg Kroah-Hartman). Thank you.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- /*****************************************************************************/
-
-/* Standard Linux module include files */
-#include <asm/uaccess.h>
-#include <asm/byteorder.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-
-/*-------------------------------------------------------------------*/
-/* Debug support                                                    */
-#ifdef DEBUG
-#define dump( adr, len) \
-do {                   \
-       unsigned int u; \
-       printk (KERN_DEBUG); \
-       for (u = 0; u < len; u++) \
-               printk (" %02X", adr[u] & 0xFF); \
-       printk ("\n"); \
-} while (0)
-#else
-#define dump( adr, len)
-#endif
-
-/*-------------------------------------------------------------------*/
-/* Version Information */
-#define DRIVER_VERSION "0.9.11"
-#define DRIVER_AUTHOR  "Wolfgang Mües <wolfgang@iksw-muees.de>"
-#define DRIVER_DESC    "Auerswald PBX/System Telephone usb driver"
-
-/*-------------------------------------------------------------------*/
-/* Private declarations for Auerswald USB driver                     */
-
-/* Auerswald Vendor ID */
-#define ID_AUERSWALD   0x09BF
-
-#define AUER_MINOR_BASE        112     /* auerswald driver minor number */
-
-/* we can have up to this number of device plugged in at once */
-#define AUER_MAX_DEVICES 16
-
-
-/* Number of read buffers for each device */
-#define AU_RBUFFERS     10
-
-/* Number of chain elements for each control chain */
-#define AUCH_ELEMENTS   20
-
-/* Number of retries in communication */
-#define AU_RETRIES     10
-
-/*-------------------------------------------------------------------*/
-/* vendor specific protocol                                          */
-/* Header Byte */
-#define AUH_INDIRMASK   0x80    /* mask for direct/indirect bit */
-#define AUH_DIRECT      0x00    /* data is for USB device */
-#define AUH_INDIRECT    0x80    /* USB device is relay */
-
-#define AUH_SPLITMASK   0x40    /* mask for split bit */
-#define AUH_UNSPLIT     0x00    /* data block is full-size */
-#define AUH_SPLIT       0x40    /* data block is part of a larger one,
-                                   split-byte follows */
-
-#define AUH_TYPEMASK    0x3F    /* mask for type of data transfer */
-#define AUH_TYPESIZE    0x40    /* different types */
-#define AUH_DCHANNEL    0x00    /* D channel data */
-#define AUH_B1CHANNEL   0x01    /* B1 channel transparent */
-#define AUH_B2CHANNEL   0x02    /* B2 channel transparent */
-/*                0x03..0x0F       reserved for driver internal use */
-#define AUH_COMMAND     0x10    /* Command channel */
-#define AUH_BPROT       0x11    /* Configuration block protocol */
-#define AUH_DPROTANA    0x12    /* D channel protocol analyzer */
-#define AUH_TAPI        0x13    /* telephone api data (ATD) */
-/*                0x14..0x3F       reserved for other protocols */
-#define AUH_UNASSIGNED  0xFF    /* if char device has no assigned service */
-#define AUH_FIRSTUSERCH 0x11    /* first channel which is available for driver users */
-
-#define AUH_SIZE       1       /* Size of Header Byte */
-
-/* Split Byte. Only present if split bit in header byte set.*/
-#define AUS_STARTMASK   0x80    /* mask for first block of splitted frame */
-#define AUS_FIRST       0x80    /* first block */
-#define AUS_FOLLOW      0x00    /* following block */
-
-#define AUS_ENDMASK     0x40    /* mask for last block of splitted frame */
-#define AUS_END         0x40    /* last block */
-#define AUS_NOEND       0x00    /* not the last block */
-
-#define AUS_LENMASK     0x3F    /* mask for block length information */
-
-/* Request types */
-#define AUT_RREQ        (USB_DIR_IN  | USB_TYPE_VENDOR | USB_RECIP_OTHER)   /* Read Request */
-#define AUT_WREQ        (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER)   /* Write Request */
-
-/* Vendor Requests */
-#define AUV_GETINFO     0x00    /* GetDeviceInfo */
-#define AUV_WBLOCK      0x01    /* Write Block */
-#define AUV_RBLOCK      0x02    /* Read Block */
-#define AUV_CHANNELCTL  0x03    /* Channel Control */
-#define AUV_DUMMY      0x04    /* Dummy Out for retry */
-
-/* Device Info Types */
-#define AUDI_NUMBCH     0x0000  /* Number of supported B channels */
-#define AUDI_OUTFSIZE   0x0001  /* Size of OUT B channel fifos */
-#define AUDI_MBCTRANS   0x0002  /* max. Blocklength of control transfer */
-
-/* Interrupt endpoint definitions */
-#define AU_IRQENDP      1       /* Endpoint number */
-#define AU_IRQCMDID     16      /* Command-block ID */
-#define AU_BLOCKRDY     0       /* Command: Block data ready on ctl endpoint */
-#define AU_IRQMINSIZE  5       /* Nr. of bytes decoded in this driver */
-
-/* Device String Descriptors */
-#define AUSI_VENDOR    1       /* "Auerswald GmbH & Co. KG" */
-#define AUSI_DEVICE    2       /* Name of the Device */
-#define AUSI_SERIALNR  3       /* Serial Number */
-#define AUSI_MSN       4       /* "MSN ..." (first) Multiple Subscriber Number */
-
-#define AUSI_DLEN      100     /* Max. Length of Device Description */
-
-#define AUV_RETRY      0x101   /* First Firmware version which can do control retries */
-
-/*-------------------------------------------------------------------*/
-/* External data structures / Interface                              */
-typedef struct
-{
-       char __user *buf;       /* return buffer for string contents */
-       unsigned int bsize;     /* size of return buffer */
-} audevinfo_t,*paudevinfo_t;
-
-/* IO controls */
-#define IOCTL_AU_SLEN    _IOR( 'U', 0xF0, int)         /* return the max. string descriptor length */
-#define IOCTL_AU_DEVINFO  _IOWR('U', 0xF1, audevinfo_t) /* get name of a specific device */
-#define IOCTL_AU_SERVREQ  _IOW( 'U', 0xF2, int)        /* request a service channel */
-#define IOCTL_AU_BUFLEN          _IOR( 'U', 0xF3, int)         /* return the max. buffer length for the device */
-#define IOCTL_AU_RXAVAIL  _IOR( 'U', 0xF4, int)         /* return != 0 if Receive Data available */
-#define IOCTL_AU_CONNECT  _IOR( 'U', 0xF5, int)         /* return != 0 if connected to a service channel */
-#define IOCTL_AU_TXREADY  _IOR( 'U', 0xF6, int)         /* return != 0 if Transmitt channel ready to send */
-/*                              'U'  0xF7..0xFF reseved */
-
-/*-------------------------------------------------------------------*/
-/* Internal data structures                                          */
-
-/* ..................................................................*/
-/* urb chain element */
-struct  auerchain;                      /* forward for circular reference */
-typedef struct
-{
-        struct auerchain *chain;        /* pointer to the chain to which this element belongs */
-        struct urb * urbp;                   /* pointer to attached urb */
-        void *context;                  /* saved URB context */
-        usb_complete_t complete;        /* saved URB completion function */
-        struct list_head list;          /* to include element into a list */
-} auerchainelement_t,*pauerchainelement_t;
-
-/* urb chain */
-typedef struct auerchain
-{
-        pauerchainelement_t active;     /* element which is submitted to urb */
-       spinlock_t lock;                /* protection agains interrupts */
-        struct list_head waiting_list;  /* list of waiting elements */
-        struct list_head free_list;     /* list of available elements */
-} auerchain_t,*pauerchain_t;
-
-/* urb blocking completion helper struct */
-typedef struct
-{
-       wait_queue_head_t wqh;          /* wait for completion */
-       unsigned int done;              /* completion flag */
-} auerchain_chs_t,*pauerchain_chs_t;
-
-/* ...................................................................*/
-/* buffer element */
-struct  auerbufctl;                     /* forward */
-typedef struct
-{
-        char *bufp;                     /* reference to allocated data buffer */
-        unsigned int len;               /* number of characters in data buffer */
-       unsigned int retries;           /* for urb retries */
-        struct usb_ctrlrequest *dr;    /* for setup data in control messages */
-        struct urb * urbp;                   /* USB urb */
-        struct auerbufctl *list;        /* pointer to list */
-        struct list_head buff_list;     /* reference to next buffer in list */
-} auerbuf_t,*pauerbuf_t;
-
-/* buffer list control block */
-typedef struct auerbufctl
-{
-        spinlock_t lock;                /* protection in interrupt */
-        struct list_head free_buff_list;/* free buffers */
-        struct list_head rec_buff_list; /* buffers with receive data */
-} auerbufctl_t,*pauerbufctl_t;
-
-/* ...................................................................*/
-/* service context */
-struct  auerscon;                       /* forward */
-typedef void (*auer_dispatch_t)(struct auerscon*, pauerbuf_t);
-typedef void (*auer_disconn_t) (struct auerscon*);
-typedef struct auerscon
-{
-        unsigned int id;                /* protocol service id AUH_xxxx */
-        auer_dispatch_t dispatch;       /* dispatch read buffer */
-       auer_disconn_t disconnect;      /* disconnect from device, wake up all char readers */
-} auerscon_t,*pauerscon_t;
-
-/* ...................................................................*/
-/* USB device context */
-typedef struct
-{
-       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 */
-       int                     open_count;         /* count the number of open character channels */
-        char                   dev_desc[AUSI_DLEN];/* for storing a textual description */
-        unsigned int           maxControlLength;   /* max. Length of control paket (without header) */
-        struct urb *           inturbp;            /* interrupt urb */
-        char *                 intbufp;            /* data buffer for interrupt urb */
-       unsigned int            irqsize;            /* size of interrupt endpoint 1 */
-        struct auerchain       controlchain;       /* for chaining of control messages */
-       auerbufctl_t            bufctl;             /* Buffer control for control transfers */
-        pauerscon_t            services[AUH_TYPESIZE];/* context pointers for each service */
-       unsigned int            version;            /* Version of the device */
-       wait_queue_head_t       bufferwait;         /* wait for a control buffer */
-} auerswald_t,*pauerswald_t;
-
-/* ................................................................... */
-/* character device context */
-typedef struct
-{
-       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 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 */
-} auerchar_t,*pauerchar_t;
-
-
-/*-------------------------------------------------------------------*/
-/* Forwards */
-static void auerswald_ctrlread_complete (struct urb * urb);
-static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp);
-static struct usb_driver auerswald_driver;
-
-
-/*-------------------------------------------------------------------*/
-/* USB chain helper functions                                        */
-/* --------------------------                                        */
-
-/* completion function for chained urbs */
-static void auerchain_complete (struct urb * urb)
-{
-       unsigned long flags;
-        int result;
-
-        /* get pointer to element and to chain */
-       pauerchainelement_t acep = urb->context;
-        pauerchain_t         acp = acep->chain;
-
-        /* restore original entries in urb */
-        urb->context  = acep->context;
-        urb->complete = acep->complete;
-
-        dbg ("auerchain_complete called");
-
-        /* call original completion function
-           NOTE: this function may lead to more urbs submitted into the chain.
-                 (no chain lock at calling complete()!)
-                 acp->active != NULL is protecting us against recursion.*/
-        urb->complete (urb);
-
-        /* detach element from chain data structure */
-       spin_lock_irqsave (&acp->lock, flags);
-        if (acp->active != acep) /* paranoia debug check */
-               dbg ("auerchain_complete: completion on non-active element called!");
-        else
-                acp->active = NULL;
-
-        /* add the used chain element to the list of free elements */
-       list_add_tail (&acep->list, &acp->free_list);
-        acep = NULL;
-
-        /* is there a new element waiting in the chain? */
-        if (!acp->active && !list_empty (&acp->waiting_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = acp->waiting_list.next;
-                list_del (tmp);
-                acep = list_entry (tmp, auerchainelement_t, list);
-                acp->active = acep;
-        }
-        spin_unlock_irqrestore (&acp->lock, flags);
-
-        /* submit the new urb */
-        if (acep) {
-                urb    = acep->urbp;
-                dbg ("auerchain_complete: submitting next urb from chain");
-               urb->status = 0;        /* needed! */
-               result = usb_submit_urb(urb, GFP_ATOMIC);
-
-                /* check for submit errors */
-                if (result) {
-                        urb->status = result;
-                        dbg("auerchain_complete: usb_submit_urb with error code %d", result);
-                        /* and do error handling via *this* completion function (recursive) */
-                        auerchain_complete( urb);
-                }
-        } else {
-                /* simple return without submitting a new urb.
-                   The empty chain is detected with acp->active == NULL. */
-        };
-}
-
-
-/* submit function for chained urbs
-   this function may be called from completion context or from user space!
-   early = 1 -> submit in front of chain
-*/
-static int auerchain_submit_urb_list (pauerchain_t acp, struct urb * urb, int early)
-{
-        int result;
-        unsigned long flags;
-        pauerchainelement_t acep = NULL;
-
-        dbg ("auerchain_submit_urb called");
-
-        /* try to get a chain element */
-        spin_lock_irqsave (&acp->lock, flags);
-        if (!list_empty (&acp->free_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = acp->free_list.next;
-                list_del (tmp);
-                acep = list_entry (tmp, auerchainelement_t, list);
-        }
-        spin_unlock_irqrestore (&acp->lock, flags);
-
-        /* if no chain element available: return with error */
-        if (!acep) {
-                return -ENOMEM;
-        }
-
-        /* fill in the new chain element values */
-        acep->chain    = acp;
-        acep->context  = urb->context;
-        acep->complete = urb->complete;
-        acep->urbp     = urb;
-        INIT_LIST_HEAD (&acep->list);
-
-        /* modify urb */
-        urb->context   = acep;
-        urb->complete  = auerchain_complete;
-        urb->status    = -EINPROGRESS;    /* usb_submit_urb does this, too */
-
-        /* add element to chain - or start it immediately */
-        spin_lock_irqsave (&acp->lock, flags);
-        if (acp->active) {
-                /* there is traffic in the chain, simple add element to chain */
-               if (early) {
-                       dbg ("adding new urb to head of chain");
-                       list_add (&acep->list, &acp->waiting_list);
-               } else {
-                       dbg ("adding new urb to end of chain");
-                       list_add_tail (&acep->list, &acp->waiting_list);
-               }
-               acep = NULL;
-        } else {
-                /* the chain is empty. Prepare restart */
-                acp->active = acep;
-        }
-        /* Spin has to be removed before usb_submit_urb! */
-        spin_unlock_irqrestore (&acp->lock, flags);
-
-        /* Submit urb if immediate restart */
-        if (acep) {
-                dbg("submitting urb immediate");
-               urb->status = 0;        /* needed! */
-                result = usb_submit_urb(urb, GFP_ATOMIC);
-                /* check for submit errors */
-                if (result) {
-                        urb->status = result;
-                        dbg("auerchain_submit_urb: usb_submit_urb with error code %d", result);
-                        /* and do error handling via completion function */
-                        auerchain_complete( urb);
-                }
-        }
-
-        return 0;
-}
-
-/* submit function for chained urbs
-   this function may be called from completion context or from user space!
-*/
-static int auerchain_submit_urb (pauerchain_t acp, struct urb * urb)
-{
-       return auerchain_submit_urb_list (acp, urb, 0);
-}
-
-/* cancel an urb which is submitted to the chain
-   the result is 0 if the urb is cancelled, or -EINPROGRESS if
-   the function is successfully started.
-*/
-static int auerchain_unlink_urb (pauerchain_t acp, struct urb * urb)
-{
-       unsigned long flags;
-        struct urb * urbp;
-        pauerchainelement_t acep;
-        struct list_head *tmp;
-
-        dbg ("auerchain_unlink_urb called");
-
-        /* search the chain of waiting elements */
-        spin_lock_irqsave (&acp->lock, flags);
-        list_for_each (tmp, &acp->waiting_list) {
-                acep = list_entry (tmp, auerchainelement_t, list);
-                if (acep->urbp == urb) {
-                        list_del (tmp);
-                        urb->context = acep->context;
-                        urb->complete = acep->complete;
-                        list_add_tail (&acep->list, &acp->free_list);
-                        spin_unlock_irqrestore (&acp->lock, flags);
-                        dbg ("unlink waiting urb");
-                        urb->status = -ENOENT;
-                        urb->complete (urb);
-                        return 0;
-                }
-        }
-        /* not found. */
-        spin_unlock_irqrestore (&acp->lock, flags);
-
-        /* get the active urb */
-        acep = acp->active;
-        if (acep) {
-                urbp = acep->urbp;
-
-                /* check if we have to cancel the active urb */
-                if (urbp == urb) {
-                        /* note that there is a race condition between the check above
-                           and the unlink() call because of no lock. This race is harmless,
-                           because the usb module will detect the unlink() after completion.
-                           We can't use the acp->lock here because the completion function
-                           wants to grab it.
-                       */
-                        dbg ("unlink active urb");
-                        return usb_unlink_urb (urbp);
-                }
-        }
-
-        /* not found anyway
-           ... is some kind of success
-       */
-        dbg ("urb to unlink not found in chain");
-        return 0;
-}
-
-/* cancel all urbs which are in the chain.
-   this function must not be called from interrupt or completion handler.
-*/
-static void auerchain_unlink_all (pauerchain_t acp)
-{
-       unsigned long flags;
-        struct urb * urbp;
-        pauerchainelement_t acep;
-
-        dbg ("auerchain_unlink_all called");
-
-        /* clear the chain of waiting elements */
-        spin_lock_irqsave (&acp->lock, flags);
-        while (!list_empty (&acp->waiting_list)) {
-                /* get the next entry */
-                struct list_head *tmp = acp->waiting_list.next;
-                list_del (tmp);
-                acep = list_entry (tmp, auerchainelement_t, list);
-                urbp = acep->urbp;
-                urbp->context = acep->context;
-                urbp->complete = acep->complete;
-                list_add_tail (&acep->list, &acp->free_list);
-                spin_unlock_irqrestore (&acp->lock, flags);
-                dbg ("unlink waiting urb");
-                urbp->status = -ENOENT;
-                urbp->complete (urbp);
-                spin_lock_irqsave (&acp->lock, flags);
-        }
-        spin_unlock_irqrestore (&acp->lock, flags);
-
-        /* clear the active urb */
-        acep = acp->active;
-        if (acep) {
-                urbp = acep->urbp;
-                dbg ("unlink active urb");
-                usb_kill_urb (urbp);
-        }
-}
-
-
-/* free the chain.
-   this function must not be called from interrupt or completion handler.
-*/
-static void auerchain_free (pauerchain_t acp)
-{
-       unsigned long flags;
-        pauerchainelement_t acep;
-
-        dbg ("auerchain_free called");
-
-        /* first, cancel all pending urbs */
-        auerchain_unlink_all (acp);
-
-        /* free the elements */
-        spin_lock_irqsave (&acp->lock, flags);
-        while (!list_empty (&acp->free_list)) {
-                /* get the next entry */
-                struct list_head *tmp = acp->free_list.next;
-                list_del (tmp);
-                spin_unlock_irqrestore (&acp->lock, flags);
-               acep = list_entry (tmp, auerchainelement_t, list);
-                kfree (acep);
-               spin_lock_irqsave (&acp->lock, flags);
-       }
-        spin_unlock_irqrestore (&acp->lock, flags);
-}
-
-
-/* Init the chain control structure */
-static void auerchain_init (pauerchain_t acp)
-{
-        /* init the chain data structure */
-        acp->active = NULL;
-       spin_lock_init (&acp->lock);
-        INIT_LIST_HEAD (&acp->waiting_list);
-        INIT_LIST_HEAD (&acp->free_list);
-}
-
-/* setup a chain.
-   It is assumed that there is no concurrency while setting up the chain
-   requirement: auerchain_init()
-*/
-static int auerchain_setup (pauerchain_t acp, unsigned int numElements)
-{
-        pauerchainelement_t acep;
-
-        dbg ("auerchain_setup called with %d elements", numElements);
-
-        /* fill the list of free elements */
-        for (;numElements; numElements--) {
-                acep = kzalloc(sizeof(auerchainelement_t), GFP_KERNEL);
-                if (!acep)
-                       goto ac_fail;
-                INIT_LIST_HEAD (&acep->list);
-                list_add_tail (&acep->list, &acp->free_list);
-        }
-        return 0;
-
-ac_fail:/* free the elements */
-        while (!list_empty (&acp->free_list)) {
-                /* get the next entry */
-                struct list_head *tmp = acp->free_list.next;
-                list_del (tmp);
-                acep = list_entry (tmp, auerchainelement_t, list);
-                kfree (acep);
-        }
-        return -ENOMEM;
-}
-
-
-/* completion handler for synchronous chained URBs */
-static void auerchain_blocking_completion (struct urb *urb)
-{
-       pauerchain_chs_t pchs = urb->context;
-       pchs->done = 1;
-       wmb();
-       wake_up (&pchs->wqh);
-}
-
-
-/* Starts chained urb and waits for completion or timeout */
-static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int timeout, int* actual_length)
-{
-       auerchain_chs_t chs;
-       int status;
-
-       dbg ("auerchain_start_wait_urb called");
-       init_waitqueue_head (&chs.wqh);
-       chs.done = 0;
-
-       urb->context = &chs;
-       status = auerchain_submit_urb (acp, urb);
-       if (status)
-               /* something went wrong */
-               return status;
-
-       timeout = wait_event_timeout(chs.wqh, chs.done, timeout);
-
-       if (!timeout && !chs.done) {
-               if (urb->status != -EINPROGRESS) {      /* No callback?!! */
-                       dbg ("auerchain_start_wait_urb: raced timeout");
-                       status = urb->status;
-               } else {
-                       dbg ("auerchain_start_wait_urb: timeout");
-                       auerchain_unlink_urb (acp, urb);  /* remove urb safely */
-                       status = -ETIMEDOUT;
-               }
-       } else
-               status = urb->status;
-
-       if (status >= 0)
-               *actual_length = urb->actual_length;
-
-       return status;
-}
-
-
-/* auerchain_control_msg - Builds a control urb, sends it off and waits for completion
-   acp: pointer to the auerchain
-   dev: pointer to the usb device to send the message to
-   pipe: endpoint "pipe" to send the message to
-   request: USB message request value
-   requesttype: USB message request type value
-   value: USB message value
-   index: USB message index value
-   data: pointer to the data to send
-   size: length in bytes of the data to send
-   timeout: time to wait for the message to complete before timing out (if 0 the wait is forever)
-
-   This function sends a simple control message to a specified endpoint
-   and waits for the message to complete, or timeout.
-
-   If successful, it returns the transferred length, otherwise a negative error number.
-
-   Don't use this function from within an interrupt context, like a
-   bottom half handler.  If you need an asynchronous message, or need to send
-   a message from within interrupt context, use auerchain_submit_urb()
-*/
-static int auerchain_control_msg (pauerchain_t acp, struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
-                                 __u16 value, __u16 index, void *data, __u16 size, int timeout)
-{
-       int ret;
-       struct usb_ctrlrequest *dr;
-       struct urb *urb;
-        int uninitialized_var(length);
-
-        dbg ("auerchain_control_msg");
-        dr = kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
-       if (!dr)
-               return -ENOMEM;
-       urb = usb_alloc_urb (0, GFP_KERNEL);
-       if (!urb) {
-               kfree (dr);
-               return -ENOMEM;
-        }
-
-       dr->bRequestType = requesttype;
-       dr->bRequest = request;
-       dr->wValue  = cpu_to_le16 (value);
-       dr->wIndex  = cpu_to_le16 (index);
-       dr->wLength = cpu_to_le16 (size);
-
-       usb_fill_control_urb (urb, dev, pipe, (unsigned char*)dr, data, size,    /* build urb */
-                         auerchain_blocking_completion, NULL);
-       ret = auerchain_start_wait_urb (acp, urb, timeout, &length);
-
-       usb_free_urb (urb);
-       kfree (dr);
-
-        if (ret < 0)
-               return ret;
-       else
-               return length;
-}
-
-
-/*-------------------------------------------------------------------*/
-/* Buffer List helper functions                                      */
-
-/* free a single auerbuf */
-static void auerbuf_free (pauerbuf_t bp)
-{
-       kfree(bp->bufp);
-       kfree(bp->dr);
-       usb_free_urb(bp->urbp);
-       kfree(bp);
-}
-
-/* free the buffers from an auerbuf list */
-static void auerbuf_free_list (struct list_head *q)
-{
-        struct list_head *tmp;
-       struct list_head *p;
-       pauerbuf_t bp;
-
-       dbg ("auerbuf_free_list");
-       for (p = q->next; p != q;) {
-               bp = list_entry (p, auerbuf_t, buff_list);
-               tmp = p->next;
-               list_del (p);
-               p = tmp;
-               auerbuf_free (bp);
-       }
-}
-
-/* init the members of a list control block */
-static void auerbuf_init (pauerbufctl_t bcp)
-{
-       dbg ("auerbuf_init");
-       spin_lock_init (&bcp->lock);
-        INIT_LIST_HEAD (&bcp->free_buff_list);
-        INIT_LIST_HEAD (&bcp->rec_buff_list);
-}
-
-/* free all buffers from an auerbuf chain */
-static void auerbuf_free_buffers (pauerbufctl_t bcp)
-{
-       unsigned long flags;
-       dbg ("auerbuf_free_buffers");
-
-        spin_lock_irqsave (&bcp->lock, flags);
-
-       auerbuf_free_list (&bcp->free_buff_list);
-       auerbuf_free_list (&bcp->rec_buff_list);
-
-        spin_unlock_irqrestore (&bcp->lock, flags);
-}
-
-/* setup a list of buffers */
-/* requirement: auerbuf_init() */
-static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned int bufsize)
-{
-        pauerbuf_t bep = NULL;
-
-        dbg ("auerbuf_setup called with %d elements of %d bytes", numElements, bufsize);
-
-        /* fill the list of free elements */
-        for (;numElements; numElements--) {
-                bep = kzalloc(sizeof(auerbuf_t), GFP_KERNEL);
-                if (!bep)
-                       goto bl_fail;
-                bep->list = bcp;
-                INIT_LIST_HEAD (&bep->buff_list);
-                bep->bufp = kmalloc (bufsize, GFP_KERNEL);
-                if (!bep->bufp)
-                       goto bl_fail;
-                bep->dr = kmalloc(sizeof (struct usb_ctrlrequest), GFP_KERNEL);
-                if (!bep->dr)
-                       goto bl_fail;
-                bep->urbp = usb_alloc_urb (0, GFP_KERNEL);
-                if (!bep->urbp)
-                       goto bl_fail;
-                list_add_tail (&bep->buff_list, &bcp->free_buff_list);
-        }
-        return 0;
-
-bl_fail:/* not enough memory. Free allocated elements */
-        dbg ("auerbuf_setup: no more memory");
-       auerbuf_free(bep);
-        auerbuf_free_buffers (bcp);
-        return -ENOMEM;
-}
-
-/* insert a used buffer into the free list */
-static void auerbuf_releasebuf( pauerbuf_t bp)
-{
-        unsigned long flags;
-        pauerbufctl_t bcp = bp->list;
-       bp->retries = 0;
-
-        dbg ("auerbuf_releasebuf called");
-        spin_lock_irqsave (&bcp->lock, flags);
-       list_add_tail (&bp->buff_list, &bcp->free_buff_list);
-        spin_unlock_irqrestore (&bcp->lock, flags);
-}
-
-
-/*-------------------------------------------------------------------*/
-/* Completion handlers */
-
-/* Values of urb->status or results of usb_submit_urb():
-0              Initial, OK
--EINPROGRESS   during submission until end
--ENOENT                if urb is unlinked
--ETIME         Device did not respond
--ENOMEM                Memory Overflow
--ENODEV                Specified USB-device or bus doesn't exist
--ENXIO         URB already queued
--EINVAL                a) Invalid transfer type specified (or not supported)
-               b) Invalid interrupt interval (0n256)
--EAGAIN                a) Specified ISO start frame too early
-               b) (using ISO-ASAP) Too much scheduled for the future wait some time and try again.
--EFBIG         Too much ISO frames requested (currently uhci900)
--EPIPE         Specified pipe-handle/Endpoint is already stalled
--EMSGSIZE      Endpoint message size is zero, do interface/alternate setting
--EPROTO                a) Bitstuff error
-               b) Unknown USB error
--EILSEQ                CRC mismatch
--ENOSR         Buffer error
--EREMOTEIO     Short packet detected
--EXDEV         ISO transfer only partially completed look at individual frame status for details
--EINVAL                ISO madness, if this happens: Log off and go home
--EOVERFLOW     babble
-*/
-
-/* check if a status code allows a retry */
-static int auerswald_status_retry (int status)
-{
-       switch (status) {
-       case 0:
-       case -ETIME:
-       case -EOVERFLOW:
-       case -EAGAIN:
-       case -EPIPE:
-       case -EPROTO:
-       case -EILSEQ:
-       case -ENOSR:
-       case -EREMOTEIO:
-               return 1; /* do a retry */
-       }
-       return 0;       /* no retry possible */
-}
-
-/* Completion of asynchronous write block */
-static void auerchar_ctrlwrite_complete (struct urb * urb)
-{
-       pauerbuf_t bp =  urb->context;
-       pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
-       dbg ("auerchar_ctrlwrite_complete called");
-
-       /* reuse the buffer */
-       auerbuf_releasebuf (bp);
-       /* Wake up all processes waiting for a buffer */
-       wake_up (&cp->bufferwait);
-}
-
-/* Completion handler for dummy retry packet */
-static void auerswald_ctrlread_wretcomplete (struct urb * urb)
-{
-       pauerbuf_t bp = urb->context;
-        pauerswald_t cp;
-       int ret;
-       int status = urb->status;
-
-        dbg ("auerswald_ctrlread_wretcomplete called");
-        dbg ("complete with status: %d", status);
-       cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
-
-       /* check if it is possible to advance */
-       if (!auerswald_status_retry(status) || !cp->usbdev) {
-               /* reuse the buffer */
-               err ("control dummy: transmission error %d, can not retry", status);
-               auerbuf_releasebuf (bp);
-               /* Wake up all processes waiting for a buffer */
-               wake_up (&cp->bufferwait);
-               return;
-       }
-
-       /* fill the control message */
-       bp->dr->bRequestType = AUT_RREQ;
-       bp->dr->bRequest     = AUV_RBLOCK;
-       bp->dr->wLength      = bp->dr->wValue;  /* temporary stored */
-       bp->dr->wValue       = cpu_to_le16 (1); /* Retry Flag */
-       /* bp->dr->index    = channel id;          remains */
-       usb_fill_control_urb (bp->urbp, cp->usbdev, usb_rcvctrlpipe (cp->usbdev, 0),
-                          (unsigned char*)bp->dr, bp->bufp, le16_to_cpu (bp->dr->wLength),
-                         auerswald_ctrlread_complete,bp);
-
-       /* submit the control msg as next paket */
-       ret = auerchain_submit_urb_list (&cp->controlchain, bp->urbp, 1);
-        if (ret) {
-               dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
-               bp->urbp->status = ret;
-               auerswald_ctrlread_complete (bp->urbp);
-       }
-}
-
-/* completion handler for receiving of control messages */
-static void auerswald_ctrlread_complete (struct urb * urb)
-{
-        unsigned int  serviceid;
-        pauerswald_t  cp;
-        pauerscon_t   scp;
-       pauerbuf_t bp = urb->context;
-       int status = urb->status;
-       int ret;
-
-        dbg ("auerswald_ctrlread_complete called");
-
-       cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
-
-       /* check if there is valid data in this urb */
-        if (status) {
-               dbg ("complete with non-zero status: %d", status);
-               /* should we do a retry? */
-               if (!auerswald_status_retry(status)
-                || !cp->usbdev
-                || (cp->version < AUV_RETRY)
-                 || (bp->retries >= AU_RETRIES)) {
-                       /* reuse the buffer */
-                       err ("control read: transmission error %d, can not retry", status);
-                       auerbuf_releasebuf (bp);
-                       /* Wake up all processes waiting for a buffer */
-                       wake_up (&cp->bufferwait);
-                       return;
-               }
-               bp->retries++;
-               dbg ("Retry count = %d", bp->retries);
-               /* send a long dummy control-write-message to allow device firmware to react */
-               bp->dr->bRequestType = AUT_WREQ;
-               bp->dr->bRequest     = AUV_DUMMY;
-               bp->dr->wValue       = bp->dr->wLength; /* temporary storage */
-               // bp->dr->wIndex    channel ID remains
-               bp->dr->wLength      = cpu_to_le16 (32); /* >= 8 bytes */
-               usb_fill_control_urb (bp->urbp, cp->usbdev, usb_sndctrlpipe (cp->usbdev, 0),
-                       (unsigned char*)bp->dr, bp->bufp, 32,
-                       auerswald_ctrlread_wretcomplete,bp);
-
-               /* submit the control msg as next paket */
-                       ret = auerchain_submit_urb_list (&cp->controlchain, bp->urbp, 1);
-                       if (ret) {
-                               dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
-                               bp->urbp->status = ret;
-                               auerswald_ctrlread_wretcomplete (bp->urbp);
-               }
-                return;
-        }
-
-        /* get the actual bytecount (incl. headerbyte) */
-        bp->len = urb->actual_length;
-        serviceid = bp->bufp[0] & AUH_TYPEMASK;
-        dbg ("Paket with serviceid %d and %d bytes received", serviceid, bp->len);
-
-        /* dispatch the paket */
-        scp = cp->services[serviceid];
-        if (scp) {
-                /* look, Ma, a listener! */
-                scp->dispatch (scp, bp);
-        }
-
-        /* release the paket */
-        auerbuf_releasebuf (bp);
-       /* Wake up all processes waiting for a buffer */
-       wake_up (&cp->bufferwait);
-}
-
-/*-------------------------------------------------------------------*/
-/* Handling of Interrupt Endpoint                                    */
-/* This interrupt Endpoint is used to inform the host about waiting
-   messages from the USB device.
-*/
-/* int completion handler. */
-static void auerswald_int_complete (struct urb * urb)
-{
-        unsigned long flags;
-        unsigned  int channelid;
-        unsigned  int bytecount;
-        int ret;
-       int status = urb->status;
-        pauerbuf_t   bp = NULL;
-       pauerswald_t cp = urb->context;
-
-        dbg ("%s called", __func__);
-
-       switch (status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __func__, status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __func__, status);
-               goto exit;
-       }
-
-        /* check if all needed data was received */
-       if (urb->actual_length < AU_IRQMINSIZE) {
-                dbg ("invalid data length received: %d bytes", urb->actual_length);
-               goto exit;
-        }
-
-        /* check the command code */
-        if (cp->intbufp[0] != AU_IRQCMDID) {
-                dbg ("invalid command received: %d", cp->intbufp[0]);
-               goto exit;
-        }
-
-        /* check the command type */
-        if (cp->intbufp[1] != AU_BLOCKRDY) {
-                dbg ("invalid command type received: %d", cp->intbufp[1]);
-               goto exit;
-        }
-
-        /* now extract the information */
-        channelid = cp->intbufp[2];
-        bytecount = (unsigned char)cp->intbufp[3];
-        bytecount |= (unsigned char)cp->intbufp[4] << 8;
-
-        /* check the channel id */
-        if (channelid >= AUH_TYPESIZE) {
-                dbg ("invalid channel id received: %d", channelid);
-               goto exit;
-        }
-
-        /* check the byte count */
-        if (bytecount > (cp->maxControlLength+AUH_SIZE)) {
-                dbg ("invalid byte count received: %d", bytecount);
-               goto exit;
-        }
-        dbg ("Service Channel = %d", channelid);
-        dbg ("Byte Count = %d", bytecount);
-
-        /* get a buffer for the next data paket */
-        spin_lock_irqsave (&cp->bufctl.lock, flags);
-        if (!list_empty (&cp->bufctl.free_buff_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = cp->bufctl.free_buff_list.next;
-                list_del (tmp);
-                bp = list_entry (tmp, auerbuf_t, buff_list);
-        }
-        spin_unlock_irqrestore (&cp->bufctl.lock, flags);
-
-        /* if no buffer available: skip it */
-        if (!bp) {
-                dbg ("auerswald_int_complete: no data buffer available");
-                /* can we do something more?
-                  This is a big problem: if this int packet is ignored, the
-                  device will wait forever and not signal any more data.
-                  The only real solution is: having enough buffers!
-                  Or perhaps temporary disabling the int endpoint?
-               */
-               goto exit;
-        }
-
-       /* fill the control message */
-        bp->dr->bRequestType = AUT_RREQ;
-       bp->dr->bRequest     = AUV_RBLOCK;
-       bp->dr->wValue       = cpu_to_le16 (0);
-       bp->dr->wIndex       = cpu_to_le16 (channelid | AUH_DIRECT | AUH_UNSPLIT);
-       bp->dr->wLength      = cpu_to_le16 (bytecount);
-       usb_fill_control_urb (bp->urbp, cp->usbdev, usb_rcvctrlpipe (cp->usbdev, 0),
-                          (unsigned char*)bp->dr, bp->bufp, bytecount,
-                         auerswald_ctrlread_complete,bp);
-
-        /* submit the control msg */
-        ret = auerchain_submit_urb (&cp->controlchain, bp->urbp);
-        if (ret) {
-                dbg ("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret);
-                bp->urbp->status = ret;
-                auerswald_ctrlread_complete( bp->urbp);
-               /* here applies the same problem as above: device locking! */
-        }
-exit:
-       ret = usb_submit_urb (urb, GFP_ATOMIC);
-       if (ret)
-               err ("%s - usb_submit_urb failed with result %d",
-                    __func__, ret);
-}
-
-/* int memory deallocation
-   NOTE: no mutex please!
-*/
-static void auerswald_int_free (pauerswald_t cp)
-{
-       if (cp->inturbp) {
-               usb_free_urb(cp->inturbp);
-               cp->inturbp = NULL;
-       }
-       kfree(cp->intbufp);
-       cp->intbufp = NULL;
-}
-
-/* This function is called to activate the interrupt
-   endpoint. This function returns 0 if successful or an error code.
-   NOTE: no mutex please!
-*/
-static int auerswald_int_open (pauerswald_t cp)
-{
-        int ret;
-       struct usb_host_endpoint *ep;
-       int irqsize;
-       dbg ("auerswald_int_open");
-
-       ep = cp->usbdev->ep_in[AU_IRQENDP];
-       if (!ep) {
-               ret = -EFAULT;
-               goto intoend;
-       }
-       irqsize = le16_to_cpu(ep->desc.wMaxPacketSize);
-       cp->irqsize = irqsize;
-
-       /* allocate the urb and data buffer */
-        if (!cp->inturbp) {
-                cp->inturbp = usb_alloc_urb (0, GFP_KERNEL);
-                if (!cp->inturbp) {
-                        ret = -ENOMEM;
-                        goto intoend;
-                }
-        }
-        if (!cp->intbufp) {
-                cp->intbufp = kmalloc (irqsize, GFP_KERNEL);
-                if (!cp->intbufp) {
-                        ret = -ENOMEM;
-                        goto intoend;
-                }
-        }
-        /* setup urb */
-        usb_fill_int_urb (cp->inturbp, cp->usbdev,
-                       usb_rcvintpipe (cp->usbdev,AU_IRQENDP), cp->intbufp,
-                       irqsize, auerswald_int_complete, cp, ep->desc.bInterval);
-        /* start the urb */
-       cp->inturbp->status = 0;        /* needed! */
-       ret = usb_submit_urb (cp->inturbp, GFP_KERNEL);
-
-intoend:
-        if (ret < 0) {
-                /* activation of interrupt endpoint has failed. Now clean up. */
-                dbg ("auerswald_int_open: activation of int endpoint failed");
-
-                /* deallocate memory */
-                auerswald_int_free (cp);
-        }
-        return ret;
-}
-
-/* This function is called to deactivate the interrupt
-   endpoint. This function returns 0 if successful or an error code.
-   NOTE: no mutex please!
-*/
-static void auerswald_int_release (pauerswald_t cp)
-{
-        dbg ("auerswald_int_release");
-
-        /* stop the int endpoint */
-       usb_kill_urb (cp->inturbp);
-
-        /* deallocate memory */
-        auerswald_int_free (cp);
-}
-
-/* --------------------------------------------------------------------- */
-/* Helper functions                                                      */
-
-/* wake up waiting readers */
-static void auerchar_disconnect (pauerscon_t scp)
-{
-        pauerchar_t ccp = ((pauerchar_t)((char *)(scp)-(unsigned long)(&((pauerchar_t)0)->scontext)));
-       dbg ("auerchar_disconnect called");
-       ccp->removed = 1;
-       wake_up (&ccp->readwait);
-}
-
-
-/* dispatch a read paket to a waiting character device */
-static void auerchar_ctrlread_dispatch (pauerscon_t scp, pauerbuf_t bp)
-{
-       unsigned long flags;
-        pauerchar_t ccp;
-        pauerbuf_t newbp = NULL;
-        char * charp;
-        dbg ("auerchar_ctrlread_dispatch called");
-        ccp = ((pauerchar_t)((char *)(scp)-(unsigned long)(&((pauerchar_t)0)->scontext)));
-
-        /* get a read buffer from character device context */
-        spin_lock_irqsave (&ccp->bufctl.lock, flags);
-        if (!list_empty (&ccp->bufctl.free_buff_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = ccp->bufctl.free_buff_list.next;
-                list_del (tmp);
-                newbp = list_entry (tmp, auerbuf_t, buff_list);
-        }
-        spin_unlock_irqrestore (&ccp->bufctl.lock, flags);
-
-        if (!newbp) {
-                dbg ("No read buffer available, discard paket!");
-                return;     /* no buffer, no dispatch */
-        }
-
-        /* copy information to new buffer element
-           (all buffers have the same length) */
-        charp = newbp->bufp;
-        newbp->bufp = bp->bufp;
-        bp->bufp = charp;
-        newbp->len = bp->len;
-
-        /* insert new buffer in read list */
-        spin_lock_irqsave (&ccp->bufctl.lock, flags);
-       list_add_tail (&newbp->buff_list, &ccp->bufctl.rec_buff_list);
-        spin_unlock_irqrestore (&ccp->bufctl.lock, flags);
-        dbg ("read buffer appended to rec_list");
-
-        /* wake up pending synchronous reads */
-       wake_up (&ccp->readwait);
-}
-
-
-/* Delete an auerswald driver context */
-static void auerswald_delete( pauerswald_t cp)
-{
-       dbg( "auerswald_delete");
-       if (cp == NULL)
-               return;
-
-       /* Wake up all processes waiting for a buffer */
-       wake_up (&cp->bufferwait);
-
-       /* Cleaning up */
-       auerswald_int_release (cp);
-       auerchain_free (&cp->controlchain);
-       auerbuf_free_buffers (&cp->bufctl);
-
-       /* release the memory */
-       kfree( cp);
-}
-
-
-/* Delete an auerswald character context */
-static void auerchar_delete( pauerchar_t ccp)
-{
-       dbg ("auerchar_delete");
-       if (ccp == NULL)
-               return;
-
-        /* wake up pending synchronous reads */
-       ccp->removed = 1;
-       wake_up (&ccp->readwait);
-
-       /* remove the read buffer */
-       if (ccp->readbuf) {
-               auerbuf_releasebuf (ccp->readbuf);
-               ccp->readbuf = NULL;
-       }
-
-       /* remove the character buffers */
-       auerbuf_free_buffers (&ccp->bufctl);
-
-       /* release the memory */
-       kfree( ccp);
-}
-
-
-/* add a new service to the device
-   scp->id must be set!
-   return: 0 if OK, else error code
-*/
-static int auerswald_addservice (pauerswald_t cp, pauerscon_t scp)
-{
-       int ret;
-
-       /* is the device available? */
-       if (!cp->usbdev) {
-               dbg ("usbdev == NULL");
-               return -EIO;    /*no: can not add a service, sorry*/
-       }
-
-       /* is the service available? */
-       if (cp->services[scp->id]) {
-               dbg ("service is busy");
-                return -EBUSY;
-       }
-
-       /* device is available, service is free */
-       cp->services[scp->id] = scp;
-
-       /* register service in device */
-       ret = auerchain_control_msg(
-               &cp->controlchain,                      /* pointer to control chain */
-               cp->usbdev,                             /* pointer to device */
-               usb_sndctrlpipe (cp->usbdev, 0),        /* pipe to control endpoint */
-               AUV_CHANNELCTL,                         /* USB message request value */
-               AUT_WREQ,                               /* USB message request type value */
-               0x01,              /* open                 USB message value */
-               scp->id,                                /* USB message index value */
-               NULL,                                   /* pointer to the data to send */
-               0,                                      /* length in bytes of the data to send */
-               HZ * 2);                                /* time to wait for the message to complete before timing out */
-       if (ret < 0) {
-               dbg ("auerswald_addservice: auerchain_control_msg returned error code %d", ret);
-               /* undo above actions */
-               cp->services[scp->id] = NULL;
-               return ret;
-       }
-
-       dbg ("auerswald_addservice: channel open OK");
-       return 0;
-}
-
-
-/* remove a service from the device
-   scp->id must be set! */
-static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp)
-{
-       dbg ("auerswald_removeservice called");
-
-       /* check if we have a service allocated */
-       if (scp->id == AUH_UNASSIGNED)
-               return;
-
-       /* If there is a device: close the channel */
-       if (cp->usbdev) {
-               /* Close the service channel inside the device */
-               int ret = auerchain_control_msg(
-               &cp->controlchain,                      /* pointer to control chain */
-               cp->usbdev,                             /* pointer to device */
-               usb_sndctrlpipe (cp->usbdev, 0),        /* pipe to control endpoint */
-               AUV_CHANNELCTL,                         /* USB message request value */
-               AUT_WREQ,                               /* USB message request type value */
-               0x00,              // close             /* USB message value */
-               scp->id,                                /* USB message index value */
-               NULL,                                   /* pointer to the data to send */
-               0,                                      /* length in bytes of the data to send */
-               HZ * 2);                                /* time to wait for the message to complete before timing out */
-               if (ret < 0) {
-                       dbg ("auerswald_removeservice: auerchain_control_msg returned error code %d", ret);
-               }
-               else {
-                       dbg ("auerswald_removeservice: channel close OK");
-               }
-       }
-
-       /* remove the service from the device */
-       cp->services[scp->id] = NULL;
-       scp->id = AUH_UNASSIGNED;
-}
-
-
-/* --------------------------------------------------------------------- */
-/* Char device functions                                                 */
-
-/* Open a new character device */
-static int auerchar_open (struct inode *inode, struct file *file)
-{
-       int dtindex = iminor(inode);
-       pauerswald_t cp = NULL;
-       pauerchar_t ccp = NULL;
-       struct usb_interface *intf;
-        int ret;
-
-        /* minor number in range? */
-       if (dtindex < 0) {
-               return -ENODEV;
-        }
-       intf = usb_find_interface(&auerswald_driver, dtindex);
-       if (!intf) {
-               return -ENODEV;
-       }
-
-       /* usb device available? */
-       cp = usb_get_intfdata (intf);
-       if (cp == NULL) {
-               return -ENODEV;
-       }
-       if (mutex_lock_interruptible(&cp->mutex)) {
-               return -ERESTARTSYS;
-       }
-
-       /* we have access to the device. Now lets allocate memory */
-       ccp = kzalloc(sizeof(auerchar_t), GFP_KERNEL);
-       if (ccp == NULL) {
-               err ("out of memory");
-               ret = -ENOMEM;
-               goto ofail;
-       }
-
-       /* Initialize device descriptor */
-       mutex_init(&ccp->mutex);
-       mutex_init(&ccp->readmutex);
-        auerbuf_init (&ccp->bufctl);
-        ccp->scontext.id = AUH_UNASSIGNED;
-        ccp->scontext.dispatch = auerchar_ctrlread_dispatch;
-       ccp->scontext.disconnect = auerchar_disconnect;
-       init_waitqueue_head (&ccp->readwait);
-
-       ret = auerbuf_setup (&ccp->bufctl, AU_RBUFFERS, cp->maxControlLength+AUH_SIZE);
-               if (ret) {
-               goto ofail;
-       }
-
-       cp->open_count++;
-       ccp->auerdev = cp;
-       dbg("open %s as /dev/%s", cp->dev_desc, cp->name);
-       mutex_unlock(&cp->mutex);
-
-       /* file IO stuff */
-       file->f_pos = 0;
-       file->private_data = ccp;
-       return nonseekable_open(inode, file);
-
-       /* Error exit */
-ofail: mutex_unlock(&cp->mutex);
-       auerchar_delete (ccp);
-       return ret;
-}
-
-
-/* IOCTL functions */
-static long auerchar_ioctl(struct file *file, unsigned int cmd,
-                                                       unsigned long arg)
-{
-       pauerchar_t ccp = (pauerchar_t) file->private_data;
-       int ret = 0;
-        audevinfo_t devinfo;
-        pauerswald_t cp = NULL;
-       unsigned int u;
-       unsigned int __user *user_arg = (unsigned int __user *)arg;
-
-        dbg ("ioctl");
-
-       /* get the mutexes */
-       if (mutex_lock_interruptible(&ccp->mutex)) {
-               return -ERESTARTSYS;
-       }
-       cp = ccp->auerdev;
-       if (!cp) {
-               mutex_unlock(&ccp->mutex);
-                return -ENODEV;
-       }
-       if (mutex_lock_interruptible(&cp->mutex)) {
-               mutex_unlock(&ccp->mutex);
-               return -ERESTARTSYS;
-       }
-
-       /* Check for removal */
-       if (!cp->usbdev) {
-               mutex_unlock(&cp->mutex);
-               mutex_unlock(&ccp->mutex);
-                return -ENODEV;
-       }
-       lock_kernel();
-       switch (cmd) {
-
-       /* return != 0 if Transmitt channel ready to send */
-       case IOCTL_AU_TXREADY:
-               dbg ("IOCTL_AU_TXREADY");
-               u   = ccp->auerdev
-                  && (ccp->scontext.id != AUH_UNASSIGNED)
-                  && !list_empty (&cp->bufctl.free_buff_list);
-               ret = put_user (u, user_arg);
-               break;
-
-       /* return != 0 if connected to a service channel */
-       case IOCTL_AU_CONNECT:
-               dbg ("IOCTL_AU_CONNECT");
-               u = (ccp->scontext.id != AUH_UNASSIGNED);
-               ret = put_user (u, user_arg);
-               break;
-
-       /* return != 0 if Receive Data available */
-       case IOCTL_AU_RXAVAIL:
-               dbg ("IOCTL_AU_RXAVAIL");
-               if (ccp->scontext.id == AUH_UNASSIGNED) {
-                        ret = -EIO;
-                        break;
-                }
-               u = 0;  /* no data */
-               if (ccp->readbuf) {
-                       int restlen = ccp->readbuf->len - ccp->readoffset;
-                       if (restlen > 0)
-                               u = 1;
-               }
-               if (!u) {
-                       if (!list_empty (&ccp->bufctl.rec_buff_list)) {
-                               u = 1;
-                       }
-               }
-               ret = put_user (u, user_arg);
-               break;
-
-       /* return the max. buffer length for the device */
-       case IOCTL_AU_BUFLEN:
-               dbg ("IOCTL_AU_BUFLEN");
-               u = cp->maxControlLength;
-               ret = put_user (u, user_arg);
-               break;
-
-       /* requesting a service channel */
-        case IOCTL_AU_SERVREQ:
-               dbg ("IOCTL_AU_SERVREQ");
-                /* requesting a service means: release the previous one first */
-               auerswald_removeservice (cp, &ccp->scontext);
-               /* get the channel number */
-               ret = get_user (u, user_arg);
-               if (ret) {
-                       break;
-               }
-               if ((u < AUH_FIRSTUSERCH) || (u >= AUH_TYPESIZE)) {
-                        ret = -EIO;
-                        break;
-                }
-                dbg ("auerchar service request parameters are ok");
-               ccp->scontext.id = u;
-
-               /* request the service now */
-               ret = auerswald_addservice (cp, &ccp->scontext);
-               if (ret) {
-                       /* no: revert service entry */
-                       ccp->scontext.id = AUH_UNASSIGNED;
-               }
-               break;
-
-       /* get a string descriptor for the device */
-       case IOCTL_AU_DEVINFO:
-               dbg ("IOCTL_AU_DEVINFO");
-                if (copy_from_user (&devinfo, (void __user *) arg, sizeof (audevinfo_t))) {
-                       ret = -EFAULT;
-                       break;
-                }
-               u = strlen(cp->dev_desc)+1;
-               if (u > devinfo.bsize) {
-                       u = devinfo.bsize;
-               }
-               ret = copy_to_user(devinfo.buf, cp->dev_desc, u) ? -EFAULT : 0;
-               break;
-
-       /* get the max. string descriptor length */
-        case IOCTL_AU_SLEN:
-               dbg ("IOCTL_AU_SLEN");
-               u = AUSI_DLEN;
-               ret = put_user (u, user_arg);
-               break;
-
-       default:
-               dbg ("IOCTL_AU_UNKNOWN");
-               ret = -ENOTTY;
-               break;
-        }
-        unlock_kernel();
-       /* release the mutexes */
-       mutex_unlock(&cp->mutex);
-       mutex_unlock(&ccp->mutex);
-       return ret;
-}
-
-/* Read data from the device */
-static ssize_t auerchar_read (struct file *file, char __user *buf, size_t count, loff_t * ppos)
-{
-        unsigned long flags;
-       pauerchar_t ccp = (pauerchar_t) file->private_data;
-        pauerbuf_t   bp = NULL;
-       wait_queue_t wait;
-
-        dbg ("auerchar_read");
-
-       /* Error checking */
-       if (!ccp)
-               return -EIO;
-       if (*ppos)
-               return -ESPIPE;
-        if (count == 0)
-               return 0;
-
-       /* get the mutex */
-       if (mutex_lock_interruptible(&ccp->mutex))
-               return -ERESTARTSYS;
-
-       /* Can we expect to read something? */
-       if (ccp->scontext.id == AUH_UNASSIGNED) {
-               mutex_unlock(&ccp->mutex);
-                return -EIO;
-       }
-
-       /* only one reader per device allowed */
-       if (mutex_lock_interruptible(&ccp->readmutex)) {
-               mutex_unlock(&ccp->mutex);
-               return -ERESTARTSYS;
-       }
-
-       /* read data from readbuf, if available */
-doreadbuf:
-       bp = ccp->readbuf;
-       if (bp) {
-               /* read the maximum bytes */
-               int restlen = bp->len - ccp->readoffset;
-               if (restlen < 0)
-                       restlen = 0;
-               if (count > restlen)
-                       count = restlen;
-               if (count) {
-                       if (copy_to_user (buf, bp->bufp+ccp->readoffset, count)) {
-                               dbg ("auerswald_read: copy_to_user failed");
-                               mutex_unlock(&ccp->readmutex);
-                               mutex_unlock(&ccp->mutex);
-                               return -EFAULT;
-                       }
-               }
-               /* advance the read offset */
-               ccp->readoffset += count;
-               restlen -= count;
-               // reuse the read buffer
-               if (restlen <= 0) {
-                       auerbuf_releasebuf (bp);
-                       ccp->readbuf = NULL;
-               }
-               /* return with number of bytes read */
-               if (count) {
-                       mutex_unlock(&ccp->readmutex);
-                       mutex_unlock(&ccp->mutex);
-                       return count;
-               }
-       }
-
-       /* a read buffer is not available. Try to get the next data block. */
-doreadlist:
-       /* Preparing for sleep */
-       init_waitqueue_entry (&wait, current);
-       set_current_state (TASK_INTERRUPTIBLE);
-       add_wait_queue (&ccp->readwait, &wait);
-
-       bp = NULL;
-       spin_lock_irqsave (&ccp->bufctl.lock, flags);
-        if (!list_empty (&ccp->bufctl.rec_buff_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = ccp->bufctl.rec_buff_list.next;
-                list_del (tmp);
-                bp = list_entry (tmp, auerbuf_t, buff_list);
-        }
-        spin_unlock_irqrestore (&ccp->bufctl.lock, flags);
-
-       /* have we got data? */
-       if (bp) {
-               ccp->readbuf = bp;
-               ccp->readoffset = AUH_SIZE; /* for headerbyte */
-               set_current_state (TASK_RUNNING);
-               remove_wait_queue (&ccp->readwait, &wait);
-               goto doreadbuf;           /* now we can read! */
-       }
-
-       /* no data available. Should we wait? */
-       if (file->f_flags & O_NONBLOCK) {
-                dbg ("No read buffer available, returning -EAGAIN");
-               set_current_state (TASK_RUNNING);
-               remove_wait_queue (&ccp->readwait, &wait);
-               mutex_unlock(&ccp->readmutex);
-               mutex_unlock(&ccp->mutex);
-               return -EAGAIN;  /* nonblocking, no data available */
-        }
-
-       /* yes, we should 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 */
-               mutex_unlock(&ccp->readmutex);
-               return -ERESTARTSYS;
-       }
-
-       /* Anything left to read? */
-       if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) {
-               mutex_unlock(&ccp->readmutex);
-               return -EIO;
-       }
-
-       if (mutex_lock_interruptible(&ccp->mutex)) {
-               mutex_unlock(&ccp->readmutex);
-               return -ERESTARTSYS;
-       }
-
-       /* try to read the incoming data again */
-       goto doreadlist;
-}
-
-
-/* Write a data block into the right service channel of the device */
-static ssize_t auerchar_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
-{
-       pauerchar_t ccp = (pauerchar_t) file->private_data;
-        pauerswald_t cp = NULL;
-        pauerbuf_t bp;
-        unsigned long flags;
-       int ret;
-       wait_queue_t wait;
-
-        dbg ("auerchar_write %zd bytes", len);
-
-       /* Error checking */
-       if (!ccp)
-               return -EIO;
-        if (*ppos)
-               return -ESPIPE;
-        if (len == 0)
-                return 0;
-
-write_again:
-       /* get the mutex */
-       if (mutex_lock_interruptible(&ccp->mutex))
-               return -ERESTARTSYS;
-
-       /* Can we expect to write something? */
-       if (ccp->scontext.id == AUH_UNASSIGNED) {
-               mutex_unlock(&ccp->mutex);
-                return -EIO;
-       }
-
-       cp = ccp->auerdev;
-       if (!cp) {
-               mutex_unlock(&ccp->mutex);
-               return -ERESTARTSYS;
-       }
-       if (mutex_lock_interruptible(&cp->mutex)) {
-               mutex_unlock(&ccp->mutex);
-               return -ERESTARTSYS;
-       }
-       if (!cp->usbdev) {
-               mutex_unlock(&cp->mutex);
-               mutex_unlock(&ccp->mutex);
-               return -EIO;
-       }
-       /* Prepare for sleep */
-       init_waitqueue_entry (&wait, current);
-       set_current_state (TASK_INTERRUPTIBLE);
-       add_wait_queue (&cp->bufferwait, &wait);
-
-       /* Try to get a buffer from the device pool.
-          We can't use a buffer from ccp->bufctl because the write
-          command will last beond a release() */
-       bp = NULL;
-       spin_lock_irqsave (&cp->bufctl.lock, flags);
-        if (!list_empty (&cp->bufctl.free_buff_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = cp->bufctl.free_buff_list.next;
-                list_del (tmp);
-                bp = list_entry (tmp, auerbuf_t, buff_list);
-        }
-        spin_unlock_irqrestore (&cp->bufctl.lock, flags);
-
-       /* are there any buffers left? */
-       if (!bp) {
-               mutex_unlock(&cp->mutex);
-               mutex_unlock(&ccp->mutex);
-
-               /* NONBLOCK: don't wait */
-               if (file->f_flags & O_NONBLOCK) {
-                       set_current_state (TASK_RUNNING);
-                       remove_wait_queue (&cp->bufferwait, &wait);
-                       return -EAGAIN;
-               }
-
-               /* BLOCKING: wait */
-               schedule();
-               remove_wait_queue (&cp->bufferwait, &wait);
-               if (signal_pending (current)) {
-                       /* waked up by a signal */
-                       return -ERESTARTSYS;
-               }
-               goto write_again;
-       } else {
-               set_current_state (TASK_RUNNING);
-               remove_wait_queue (&cp->bufferwait, &wait);
-       }
-
-       /* protect against too big write requests */
-       if (len > cp->maxControlLength)
-               len = cp->maxControlLength;
-
-       /* Fill the buffer */
-       if (copy_from_user ( bp->bufp+AUH_SIZE, buf, len)) {
-               dbg ("copy_from_user failed");
-               auerbuf_releasebuf (bp);
-               /* Wake up all processes waiting for a buffer */
-               wake_up (&cp->bufferwait);
-               mutex_unlock(&cp->mutex);
-               mutex_unlock(&ccp->mutex);
-               return -EFAULT;
-       }
-
-       /* set the header byte */
-        *(bp->bufp) = ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT;
-
-       /* Set the transfer Parameters */
-       bp->len = len+AUH_SIZE;
-        bp->dr->bRequestType = AUT_WREQ;
-       bp->dr->bRequest     = AUV_WBLOCK;
-       bp->dr->wValue       = cpu_to_le16 (0);
-       bp->dr->wIndex       = cpu_to_le16 (ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT);
-       bp->dr->wLength      = cpu_to_le16 (len+AUH_SIZE);
-       usb_fill_control_urb (bp->urbp, cp->usbdev, usb_sndctrlpipe (cp->usbdev, 0),
-                   (unsigned char*)bp->dr, bp->bufp, len+AUH_SIZE,
-                   auerchar_ctrlwrite_complete, bp);
-       /* up we go */
-       ret = auerchain_submit_urb (&cp->controlchain, bp->urbp);
-       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);
-               mutex_unlock(&ccp->mutex);
-               return -EIO;
-       }
-       else {
-               dbg ("auerchar_write: Write OK");
-               mutex_unlock(&ccp->mutex);
-               return len;
-       }
-}
-
-
-/* Close a character device */
-static int auerchar_release (struct inode *inode, struct file *file)
-{
-       pauerchar_t ccp = (pauerchar_t) file->private_data;
-       pauerswald_t cp;
-       dbg("release");
-
-       mutex_lock(&ccp->mutex);
-       cp = ccp->auerdev;
-       if (cp) {
-               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 */
-                       mutex_unlock(&cp->mutex);
-                       auerswald_delete (cp);
-               } else {
-                       mutex_unlock(&cp->mutex);
-               }
-               cp = NULL;
-               ccp->auerdev = NULL;
-       }
-       mutex_unlock(&ccp->mutex);
-       auerchar_delete (ccp);
-
-       return 0;
-}
-
-
-/*----------------------------------------------------------------------*/
-/* File operation structure                                             */
-static const struct file_operations auerswald_fops =
-{
-       .owner =        THIS_MODULE,
-       .llseek =       no_llseek,
-       .read =         auerchar_read,
-       .write =        auerchar_write,
-       .unlocked_ioctl = auerchar_ioctl,
-       .open =         auerchar_open,
-       .release =      auerchar_release,
-};
-
-static struct usb_class_driver auerswald_class = {
-       .name =         "auer%d",
-       .fops =         &auerswald_fops,
-       .minor_base =   AUER_MINOR_BASE,
-};
-
-
-/* --------------------------------------------------------------------- */
-/* Special USB driver functions                                          */
-
-/* Probe if this driver wants to serve an USB device
-
-   This entry point is called whenever a new device is attached to the bus.
-   Then the device driver has to create a new instance of its internal data
-   structures for the new device.
-
-   The  dev argument specifies the device context, which contains pointers
-   to all USB descriptors. The  interface argument specifies the interface
-   number. If a USB driver wants to bind itself to a particular device and
-   interface it has to return a pointer. This pointer normally references
-   the device driver's context structure.
-
-   Probing normally is done by checking the vendor and product identifications
-   or the class and subclass definitions. If they match the interface number
-   is compared with the ones supported by the driver. When probing is done
-   class based it might be necessary to parse some more USB descriptors because
-   the device properties can differ in a wide range.
-*/
-static int auerswald_probe (struct usb_interface *intf,
-                           const struct usb_device_id *id)
-{
-       struct usb_device *usbdev = interface_to_usbdev(intf);
-       pauerswald_t cp = NULL;
-       unsigned int u = 0;
-       __le16 *pbuf;
-       int ret;
-
-       dbg ("probe: vendor id 0x%x, device id 0x%x",
-            le16_to_cpu(usbdev->descriptor.idVendor),
-            le16_to_cpu(usbdev->descriptor.idProduct));
-
-        /* we use only the first -and only- interface */
-        if (intf->altsetting->desc.bInterfaceNumber != 0)
-               return -ENODEV;
-
-       /* allocate memory for our device and initialize it */
-       cp = kzalloc (sizeof(auerswald_t), GFP_KERNEL);
-       if (cp == NULL) {
-               err ("out of memory");
-               goto pfail;
-       }
-
-       /* Initialize device descriptor */
-       mutex_init(&cp->mutex);
-       cp->usbdev = usbdev;
-       auerchain_init (&cp->controlchain);
-        auerbuf_init (&cp->bufctl);
-       init_waitqueue_head (&cp->bufferwait);
-
-       ret = usb_register_dev(intf, &auerswald_class);
-       if (ret) {
-               err ("Not able to get a minor for this device.");
-               goto pfail;
-       }
-
-       /* Give the device a name */
-       sprintf (cp->name, "usb/auer%d", intf->minor);
-
-       /* Store the index */
-       cp->dtindex = intf->minor;
-
-       /* Get the usb version of the device */
-       cp->version = le16_to_cpu(cp->usbdev->descriptor.bcdDevice);
-       dbg ("Version is %X", cp->version);
-
-       /* allow some time to settle the device */
-       msleep(334);
-
-       /* Try to get a suitable textual description of the device */
-       /* Device name:*/
-       ret = usb_string( cp->usbdev, AUSI_DEVICE, cp->dev_desc, AUSI_DLEN-1);
-       if (ret >= 0) {
-               u += ret;
-               /* Append Serial Number */
-               memcpy(&cp->dev_desc[u], ",Ser# ", 6);
-               u += 6;
-               ret = usb_string( cp->usbdev, AUSI_SERIALNR, &cp->dev_desc[u], AUSI_DLEN-u-1);
-               if (ret >= 0) {
-                       u += ret;
-                       /* Append subscriber number */
-                       memcpy(&cp->dev_desc[u], ", ", 2);
-                       u += 2;
-                       ret = usb_string( cp->usbdev, AUSI_MSN, &cp->dev_desc[u], AUSI_DLEN-u-1);
-                       if (ret >= 0) {
-                               u += ret;
-                       }
-               }
-       }
-       cp->dev_desc[u] = '\0';
-       info("device is a %s", cp->dev_desc);
-
-        /* get the maximum allowed control transfer length */
-        pbuf = kmalloc(2, GFP_KERNEL);    /* use an allocated buffer because of urb target */
-        if (!pbuf) {
-               err( "out of memory");
-               goto pfail;
-       }
-        ret = usb_control_msg(cp->usbdev,           /* pointer to device */
-                usb_rcvctrlpipe( cp->usbdev, 0 ),   /* pipe to control endpoint */
-                AUV_GETINFO,                        /* USB message request value */
-                AUT_RREQ,                           /* USB message request type value */
-                0,                                  /* USB message value */
-                AUDI_MBCTRANS,                      /* USB message index value */
-                pbuf,                               /* pointer to the receive buffer */
-                2,                                  /* length of the buffer */
-                2000);                            /* time to wait for the message to complete before timing out */
-        if (ret == 2) {
-               cp->maxControlLength = le16_to_cpup(pbuf);
-                kfree(pbuf);
-                dbg("setup: max. allowed control transfersize is %d bytes", cp->maxControlLength);
-        } else {
-                kfree(pbuf);
-                err("setup: getting max. allowed control transfer length failed with error %d", ret);
-               goto pfail;
-        }
-
-       /* allocate a chain for the control messages */
-        if (auerchain_setup (&cp->controlchain, AUCH_ELEMENTS)) {
-               err ("out of memory");
-               goto pfail;
-       }
-
-        /* allocate buffers for control messages */
-       if (auerbuf_setup (&cp->bufctl, AU_RBUFFERS, cp->maxControlLength+AUH_SIZE)) {
-               err ("out of memory");
-               goto pfail;
-       }
-
-       /* start the interrupt endpoint */
-       if (auerswald_int_open (cp)) {
-               err ("int endpoint failed");
-               goto pfail;
-       }
-
-       /* all OK */
-       usb_set_intfdata (intf, cp);
-       return 0;
-
-       /* Error exit: clean up the memory */
-pfail: auerswald_delete (cp);
-       return -EIO;
-}
-
-
-/* Disconnect driver from a served device
-
-   This function is called whenever a device which was served by this driver
-   is disconnected.
-
-   The argument  dev specifies the device context and the  driver_context
-   returns a pointer to the previously registered  driver_context of the
-   probe function. After returning from the disconnect function the USB
-   framework completely deallocates all data structures associated with
-   this device. So especially the usb_device structure must not be used
-   any longer by the usb driver.
-*/
-static void auerswald_disconnect (struct usb_interface *intf)
-{
-       pauerswald_t cp = usb_get_intfdata (intf);
-       unsigned int u;
-
-       usb_set_intfdata (intf, NULL);
-       if (!cp)
-               return;
-
-       /* give back our USB minor number */
-       usb_deregister_dev(intf, &auerswald_class);
-
-       mutex_lock(&cp->mutex);
-       info ("device /dev/%s now disconnecting", cp->name);
-
-       /* Stop the interrupt endpoint */
-       auerswald_int_release (cp);
-
-       /* remove the control chain allocated in auerswald_probe
-          This has the benefit of
-          a) all pending (a)synchronous urbs are unlinked
-          b) all buffers dealing with urbs are reclaimed
-       */
-       auerchain_free (&cp->controlchain);
-
-       if (cp->open_count == 0) {
-               /* nobody is using this device. So we can clean up now */
-               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;
-               mutex_unlock(&cp->mutex);
-               /* Terminate waiting writers */
-               wake_up (&cp->bufferwait);
-               /* Inform all waiting readers */
-               for ( u = 0; u < AUH_TYPESIZE; u++) {
-                       pauerscon_t scp = cp->services[u];
-                       if (scp)
-                               scp->disconnect( scp);
-               }
-       }
-}
-
-/* Descriptor for the devices which are served by this driver.
-   NOTE: this struct is parsed by the usbmanager install scripts.
-         Don't change without caution!
-*/
-static struct usb_device_id auerswald_ids [] = {
-       { USB_DEVICE (ID_AUERSWALD, 0x00C0) },          /* COMpact 2104 USB */
-       { USB_DEVICE (ID_AUERSWALD, 0x00DB) },          /* COMpact 4410/2206 USB */
-       { USB_DEVICE (ID_AUERSWALD, 0x00DC) }, /* COMpact 4406 DSL */
-       { USB_DEVICE (ID_AUERSWALD, 0x00DD) }, /* COMpact 2204 USB */
-       { USB_DEVICE (ID_AUERSWALD, 0x00F1) },          /* Comfort 2000 System Telephone */
-       { USB_DEVICE (ID_AUERSWALD, 0x00F2) },          /* Comfort 1200 System Telephone */
-        { }                                            /* Terminating entry */
-};
-
-/* Standard module device table */
-MODULE_DEVICE_TABLE (usb, auerswald_ids);
-
-/* Standard usb driver struct */
-static struct usb_driver auerswald_driver = {
-       .name =         "auerswald",
-       .probe =        auerswald_probe,
-       .disconnect =   auerswald_disconnect,
-       .id_table =     auerswald_ids,
-};
-
-
-/* --------------------------------------------------------------------- */
-/* Module loading/unloading                                              */
-
-/* Driver initialisation. Called after module loading.
-   NOTE: there is no concurrency at _init
-*/
-static int __init auerswald_init (void)
-{
-       int result;
-       dbg ("init");
-
-       /* register driver at the USB subsystem */
-       result = usb_register (&auerswald_driver);
-       if (result < 0) {
-               err ("driver could not be registered");
-               return -1;
-       }
-       return 0;
-}
-
-/* Driver deinit. Called before module removal.
-   NOTE: there is no concurrency at _cleanup
-*/
-static void __exit auerswald_cleanup (void)
-{
-       dbg ("cleanup");
-       usb_deregister (&auerswald_driver);
-}
-
-/* --------------------------------------------------------------------- */
-/* Linux device driver module description                                */
-
-MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_LICENSE ("GPL");
-
-module_init (auerswald_init);
-module_exit (auerswald_cleanup);
-
-/* --------------------------------------------------------------------- */
-
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
new file mode 100644 (file)
index 0000000..faca433
--- /dev/null
@@ -0,0 +1,176 @@
+#
+# USB Dual Role (OTG-ready) Controller Drivers
+# for silicon based on Mentor Graphics INVENTRA designs
+#
+
+comment "Enable Host or Gadget support to see Inventra options"
+       depends on !USB && USB_GADGET=n
+
+# (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
+config USB_MUSB_HDRC
+       depends on (USB || USB_GADGET) && HAVE_CLK
+       select TWL4030_USB if MACH_OMAP_3430SDP
+       tristate 'Inventra Highspeed Dual Role Controller (TI, ...)'
+       help
+         Say Y here if your system has a dual role high speed USB
+         controller based on the Mentor Graphics silicon IP.  Then
+         configure options to match your silicon and the board
+         it's being used with, including the USB peripheral role,
+         or the USB host role, or both.
+
+         Texas Instruments parts using this IP include DaVinci 644x,
+         OMAP 243x, OMAP 343x, and TUSB 6010.
+
+         If you do not know what this is, please say N.
+
+         To compile this driver as a module, choose M here; the
+         module will be called "musb_hdrc".
+
+config USB_MUSB_SOC
+       boolean
+       depends on USB_MUSB_HDRC
+       default y if ARCH_DAVINCI
+       default y if ARCH_OMAP2430
+       default y if ARCH_OMAP34XX
+       help
+         Use a static <asm/arch/hdrc_cnf.h> file to describe how the
+         controller is configured (endpoints, mechanisms, etc) on the
+         current iteration of a given system-on-chip.
+
+comment "DaVinci 644x USB support"
+       depends on USB_MUSB_HDRC && ARCH_DAVINCI
+
+comment "OMAP 243x high speed USB support"
+       depends on USB_MUSB_HDRC && ARCH_OMAP2430
+
+comment "OMAP 343x high speed USB support"
+       depends on USB_MUSB_HDRC && ARCH_OMAP34XX
+
+config USB_TUSB6010
+       boolean "TUSB 6010 support"
+       depends on USB_MUSB_HDRC && !USB_MUSB_SOC
+       default y
+       help
+         The TUSB 6010 chip, from Texas Instruments, connects a discrete
+         HDRC core using a 16-bit parallel bus (NOR flash style) or VLYNQ
+         (a high speed serial link).  It can use system-specific external
+         DMA controllers.
+
+choice
+       prompt "Driver Mode"
+       depends on USB_MUSB_HDRC
+       help
+         Dual-Role devices can support both host and peripheral roles,
+         as well as a the special "OTG Device" role which can switch
+         between both roles as needed.
+
+# use USB_MUSB_HDRC_HCD not USB_MUSB_HOST to #ifdef host side support;
+# OTG needs both roles, not just USB_MUSB_HOST.
+config USB_MUSB_HOST
+       depends on USB
+       bool "USB Host"
+       help
+         Say Y here if your system supports the USB host role.
+         If it has a USB "A" (rectangular), "Mini-A" (uncommon),
+         or "Mini-AB" connector, it supports the host role.
+         (With a "Mini-AB" connector, you should enable USB OTG.)
+
+# use USB_GADGET_MUSB_HDRC not USB_MUSB_PERIPHERAL to #ifdef peripheral
+# side support ... OTG needs both roles
+config USB_MUSB_PERIPHERAL
+       depends on USB_GADGET
+       bool "USB Peripheral (gadget stack)"
+       select USB_GADGET_MUSB_HDRC
+       help
+         Say Y here if your system supports the USB peripheral role.
+         If it has a USB "B" (squarish), "Mini-B", or "Mini-AB"
+         connector, it supports the peripheral role.
+         (With a "Mini-AB" connector, you should enable USB OTG.)
+
+config USB_MUSB_OTG
+       depends on USB && USB_GADGET && PM && EXPERIMENTAL
+       bool "Both host and peripheral:  USB OTG (On The Go) Device"
+       select USB_GADGET_MUSB_HDRC
+       select USB_OTG
+       help
+          The most notable feature of USB OTG is support for a
+          "Dual-Role" device, which can act as either a device
+          or a host.  The initial role choice can be changed
+          later, when two dual-role devices talk to each other.
+
+          At this writing, the OTG support in this driver is incomplete,
+          omitting the mandatory HNP or SRP protocols.  However, some
+          of the cable based role switching works.  (That is, grounding
+          the ID pin switches the controller to host mode, while leaving
+          it floating leaves it in peripheral mode.)
+
+          Select this if your system has a Mini-AB connector, or
+          to simplify certain kinds of configuration.
+
+          To implement your OTG Targeted Peripherals List (TPL), enable
+          USB_OTG_WHITELIST and update "drivers/usb/core/otg_whitelist.h"
+          to match your requirements.
+
+endchoice
+
+# enable peripheral support (including with OTG)
+config USB_GADGET_MUSB_HDRC
+       bool
+       depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
+#      default y
+#      select USB_GADGET_DUALSPEED
+#      select USB_GADGET_SELECTED
+
+# enables host support (including with OTG)
+config USB_MUSB_HDRC_HCD
+       bool
+       depends on USB_MUSB_HDRC && (USB_MUSB_HOST || USB_MUSB_OTG)
+       select USB_OTG if USB_GADGET_MUSB_HDRC
+       default y
+
+
+config MUSB_PIO_ONLY
+       bool 'Disable DMA (always use PIO)'
+       depends on USB_MUSB_HDRC
+       default y if USB_TUSB6010
+       help
+         All data is copied between memory and FIFO by the CPU.
+         DMA controllers are ignored.
+
+         Do not select 'n' here unless DMA support for your SOC or board
+         is unavailable (or unstable).  When DMA is enabled at compile time,
+         you can still disable it at run time using the "use_dma=n" module
+         parameter.
+
+config USB_INVENTRA_DMA
+       bool
+       depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY
+       default ARCH_OMAP2430 || ARCH_OMAP34XX
+       help
+         Enable DMA transfers using Mentor's engine.
+
+config USB_TI_CPPI_DMA
+       bool
+       depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY
+       default ARCH_DAVINCI
+       help
+         Enable DMA transfers when TI CPPI DMA is available.
+
+config USB_TUSB_OMAP_DMA
+       bool
+       depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY
+       depends on USB_TUSB6010
+       depends on ARCH_OMAP
+       default y
+       help
+         Enable DMA transfers on TUSB 6010 when OMAP DMA is available.
+
+config USB_MUSB_LOGLEVEL
+       depends on USB_MUSB_HDRC
+       int  'Logging Level (0 - none / 3 - annoying / ... )'
+       default 0
+       help
+         Set the logging level. 0 disables the debugging altogether,
+         although when USB_DEBUG is set the value is at least 1.
+         Starting at level 3, per-transfer (urb, usb_request, packet,
+         or dma transfer) tracing may kick in.
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
new file mode 100644 (file)
index 0000000..88eb67d
--- /dev/null
@@ -0,0 +1,86 @@
+#
+# for USB OTG silicon based on Mentor Graphics INVENTRA designs
+#
+
+musb_hdrc-objs := musb_core.o
+
+obj-$(CONFIG_USB_MUSB_HDRC)    += musb_hdrc.o
+
+ifeq ($(CONFIG_ARCH_DAVINCI),y)
+       musb_hdrc-objs  += davinci.o
+endif
+
+ifeq ($(CONFIG_USB_TUSB6010),y)
+       musb_hdrc-objs  += tusb6010.o
+endif
+
+ifeq ($(CONFIG_ARCH_OMAP2430),y)
+       musb_hdrc-objs  += omap2430.o
+endif
+
+ifeq ($(CONFIG_ARCH_OMAP3430),y)
+       musb_hdrc-objs  += omap2430.o
+endif
+
+ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y)
+       musb_hdrc-objs          += musb_gadget_ep0.o musb_gadget.o
+endif
+
+ifeq ($(CONFIG_USB_MUSB_HDRC_HCD),y)
+       musb_hdrc-objs          += musb_virthub.o musb_host.o
+endif
+
+# the kconfig must guarantee that only one of the
+# possible I/O schemes will be enabled at a time ...
+# PIO only, or DMA (several potential schemes).
+# though PIO is always there to back up DMA, and for ep0
+
+ifneq ($(CONFIG_MUSB_PIO_ONLY),y)
+
+  ifeq ($(CONFIG_USB_INVENTRA_DMA),y)
+    musb_hdrc-objs             += musbhsdma.o
+
+  else
+    ifeq ($(CONFIG_USB_TI_CPPI_DMA),y)
+      musb_hdrc-objs           += cppi_dma.o
+
+    else
+      ifeq ($(CONFIG_USB_TUSB_OMAP_DMA),y)
+        musb_hdrc-objs         += tusb6010_omap.o
+
+      endif
+    endif
+  endif
+endif
+
+
+################################################################################
+
+# FIXME remove all these extra "-DMUSB_* things, stick to CONFIG_*
+
+ifeq ($(CONFIG_USB_INVENTRA_MUSB_HAS_AHB_ID),y)
+       EXTRA_CFLAGS += -DMUSB_AHB_ID
+endif
+
+# Debugging
+
+MUSB_DEBUG:=$(CONFIG_USB_MUSB_LOGLEVEL)
+
+ifeq ("$(strip $(MUSB_DEBUG))","")
+    ifdef CONFIG_USB_DEBUG
+       MUSB_DEBUG:=1
+    else
+       MUSB_DEBUG:=0
+    endif
+endif
+
+ifneq ($(MUSB_DEBUG),0)
+    EXTRA_CFLAGS += -DDEBUG
+
+    ifeq ($(CONFIG_PROC_FS),y)
+       musb_hdrc-objs          += musb_procfs.o
+    endif
+
+endif
+
+EXTRA_CFLAGS += -DMUSB_DEBUG=$(MUSB_DEBUG)
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
new file mode 100644 (file)
index 0000000..5ad6d08
--- /dev/null
@@ -0,0 +1,1540 @@
+/*
+ * Copyright (C) 2005-2006 by Texas Instruments
+ *
+ * This file implements a DMA  interface using TI's CPPI DMA.
+ * For now it's DaVinci-only, but CPPI isn't specific to DaVinci or USB.
+ * The TUSB6020, using VLYNQ, has CPPI that looks much like DaVinci.
+ */
+
+#include <linux/usb.h>
+
+#include "musb_core.h"
+#include "cppi_dma.h"
+
+
+/* CPPI DMA status 7-mar-2006:
+ *
+ * - See musb_{host,gadget}.c for more info
+ *
+ * - Correct RX DMA generally forces the engine into irq-per-packet mode,
+ *   which can easily saturate the CPU under non-mass-storage loads.
+ *
+ * NOTES 24-aug-2006 (2.6.18-rc4):
+ *
+ * - peripheral RXDMA wedged in a test with packets of length 512/512/1.
+ *   evidently after the 1 byte packet was received and acked, the queue
+ *   of BDs got garbaged so it wouldn't empty the fifo.  (rxcsr 0x2003,
+ *   and RX DMA0: 4 left, 80000000 8feff880, 8feff860 8feff860; 8f321401
+ *   004001ff 00000001 .. 8feff860)  Host was just getting NAKed on tx
+ *   of its next (512 byte) packet.  IRQ issues?
+ *
+ * REVISIT:  the "transfer DMA" glue between CPPI and USB fifos will
+ * evidently also directly update the RX and TX CSRs ... so audit all
+ * host and peripheral side DMA code to avoid CSR access after DMA has
+ * been started.
+ */
+
+/* REVISIT now we can avoid preallocating these descriptors; or
+ * more simply, switch to a global freelist not per-channel ones.
+ * Note: at full speed, 64 descriptors == 4K bulk data.
+ */
+#define NUM_TXCHAN_BD       64
+#define NUM_RXCHAN_BD       64
+
+static inline void cpu_drain_writebuffer(void)
+{
+       wmb();
+#ifdef CONFIG_CPU_ARM926T
+       /* REVISIT this "should not be needed",
+        * but lack of it sure seemed to hurt ...
+        */
+       asm("mcr p15, 0, r0, c7, c10, 4 @ drain write buffer\n");
+#endif
+}
+
+static inline struct cppi_descriptor *cppi_bd_alloc(struct cppi_channel *c)
+{
+       struct cppi_descriptor  *bd = c->freelist;
+
+       if (bd)
+               c->freelist = bd->next;
+       return bd;
+}
+
+static inline void
+cppi_bd_free(struct cppi_channel *c, struct cppi_descriptor *bd)
+{
+       if (!bd)
+               return;
+       bd->next = c->freelist;
+       c->freelist = bd;
+}
+
+/*
+ *  Start DMA controller
+ *
+ *  Initialize the DMA controller as necessary.
+ */
+
+/* zero out entire rx state RAM entry for the channel */
+static void cppi_reset_rx(struct cppi_rx_stateram __iomem *rx)
+{
+       musb_writel(&rx->rx_skipbytes, 0, 0);
+       musb_writel(&rx->rx_head, 0, 0);
+       musb_writel(&rx->rx_sop, 0, 0);
+       musb_writel(&rx->rx_current, 0, 0);
+       musb_writel(&rx->rx_buf_current, 0, 0);
+       musb_writel(&rx->rx_len_len, 0, 0);
+       musb_writel(&rx->rx_cnt_cnt, 0, 0);
+}
+
+/* zero out entire tx state RAM entry for the channel */
+static void cppi_reset_tx(struct cppi_tx_stateram __iomem *tx, u32 ptr)
+{
+       musb_writel(&tx->tx_head, 0, 0);
+       musb_writel(&tx->tx_buf, 0, 0);
+       musb_writel(&tx->tx_current, 0, 0);
+       musb_writel(&tx->tx_buf_current, 0, 0);
+       musb_writel(&tx->tx_info, 0, 0);
+       musb_writel(&tx->tx_rem_len, 0, 0);
+       /* musb_writel(&tx->tx_dummy, 0, 0); */
+       musb_writel(&tx->tx_complete, 0, ptr);
+}
+
+static void __init cppi_pool_init(struct cppi *cppi, struct cppi_channel *c)
+{
+       int     j;
+
+       /* initialize channel fields */
+       c->head = NULL;
+       c->tail = NULL;
+       c->last_processed = NULL;
+       c->channel.status = MUSB_DMA_STATUS_UNKNOWN;
+       c->controller = cppi;
+       c->is_rndis = 0;
+       c->freelist = NULL;
+
+       /* build the BD Free list for the channel */
+       for (j = 0; j < NUM_TXCHAN_BD + 1; j++) {
+               struct cppi_descriptor  *bd;
+               dma_addr_t              dma;
+
+               bd = dma_pool_alloc(cppi->pool, GFP_KERNEL, &dma);
+               bd->dma = dma;
+               cppi_bd_free(c, bd);
+       }
+}
+
+static int cppi_channel_abort(struct dma_channel *);
+
+static void cppi_pool_free(struct cppi_channel *c)
+{
+       struct cppi             *cppi = c->controller;
+       struct cppi_descriptor  *bd;
+
+       (void) cppi_channel_abort(&c->channel);
+       c->channel.status = MUSB_DMA_STATUS_UNKNOWN;
+       c->controller = NULL;
+
+       /* free all its bds */
+       bd = c->last_processed;
+       do {
+               if (bd)
+                       dma_pool_free(cppi->pool, bd, bd->dma);
+               bd = cppi_bd_alloc(c);
+       } while (bd);
+       c->last_processed = NULL;
+}
+
+static int __init cppi_controller_start(struct dma_controller *c)
+{
+       struct cppi     *controller;
+       void __iomem    *tibase;
+       int             i;
+
+       controller = container_of(c, struct cppi, controller);
+
+       /* do whatever is necessary to start controller */
+       for (i = 0; i < ARRAY_SIZE(controller->tx); i++) {
+               controller->tx[i].transmit = true;
+               controller->tx[i].index = i;
+       }
+       for (i = 0; i < ARRAY_SIZE(controller->rx); i++) {
+               controller->rx[i].transmit = false;
+               controller->rx[i].index = i;
+       }
+
+       /* setup BD list on a per channel basis */
+       for (i = 0; i < ARRAY_SIZE(controller->tx); i++)
+               cppi_pool_init(controller, controller->tx + i);
+       for (i = 0; i < ARRAY_SIZE(controller->rx); i++)
+               cppi_pool_init(controller, controller->rx + i);
+
+       tibase =  controller->tibase;
+       INIT_LIST_HEAD(&controller->tx_complete);
+
+       /* initialise tx/rx channel head pointers to zero */
+       for (i = 0; i < ARRAY_SIZE(controller->tx); i++) {
+               struct cppi_channel     *tx_ch = controller->tx + i;
+               struct cppi_tx_stateram __iomem *tx;
+
+               INIT_LIST_HEAD(&tx_ch->tx_complete);
+
+               tx = tibase + DAVINCI_TXCPPI_STATERAM_OFFSET(i);
+               tx_ch->state_ram = tx;
+               cppi_reset_tx(tx, 0);
+       }
+       for (i = 0; i < ARRAY_SIZE(controller->rx); i++) {
+               struct cppi_channel     *rx_ch = controller->rx + i;
+               struct cppi_rx_stateram __iomem *rx;
+
+               INIT_LIST_HEAD(&rx_ch->tx_complete);
+
+               rx = tibase + DAVINCI_RXCPPI_STATERAM_OFFSET(i);
+               rx_ch->state_ram = rx;
+               cppi_reset_rx(rx);
+       }
+
+       /* enable individual cppi channels */
+       musb_writel(tibase, DAVINCI_TXCPPI_INTENAB_REG,
+                       DAVINCI_DMA_ALL_CHANNELS_ENABLE);
+       musb_writel(tibase, DAVINCI_RXCPPI_INTENAB_REG,
+                       DAVINCI_DMA_ALL_CHANNELS_ENABLE);
+
+       /* enable tx/rx CPPI control */
+       musb_writel(tibase, DAVINCI_TXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_ENABLE);
+       musb_writel(tibase, DAVINCI_RXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_ENABLE);
+
+       /* disable RNDIS mode, also host rx RNDIS autorequest */
+       musb_writel(tibase, DAVINCI_RNDIS_REG, 0);
+       musb_writel(tibase, DAVINCI_AUTOREQ_REG, 0);
+
+       return 0;
+}
+
+/*
+ *  Stop DMA controller
+ *
+ *  De-Init the DMA controller as necessary.
+ */
+
+static int cppi_controller_stop(struct dma_controller *c)
+{
+       struct cppi             *controller;
+       void __iomem            *tibase;
+       int                     i;
+
+       controller = container_of(c, struct cppi, controller);
+
+       tibase = controller->tibase;
+       /* DISABLE INDIVIDUAL CHANNEL Interrupts */
+       musb_writel(tibase, DAVINCI_TXCPPI_INTCLR_REG,
+                       DAVINCI_DMA_ALL_CHANNELS_ENABLE);
+       musb_writel(tibase, DAVINCI_RXCPPI_INTCLR_REG,
+                       DAVINCI_DMA_ALL_CHANNELS_ENABLE);
+
+       DBG(1, "Tearing down RX and TX Channels\n");
+       for (i = 0; i < ARRAY_SIZE(controller->tx); i++) {
+               /* FIXME restructure of txdma to use bds like rxdma */
+               controller->tx[i].last_processed = NULL;
+               cppi_pool_free(controller->tx + i);
+       }
+       for (i = 0; i < ARRAY_SIZE(controller->rx); i++)
+               cppi_pool_free(controller->rx + i);
+
+       /* in Tx Case proper teardown is supported. We resort to disabling
+        * Tx/Rx CPPI after cleanup of Tx channels. Before TX teardown is
+        * complete TX CPPI cannot be disabled.
+        */
+       /*disable tx/rx cppi */
+       musb_writel(tibase, DAVINCI_TXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE);
+       musb_writel(tibase, DAVINCI_RXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE);
+
+       return 0;
+}
+
+/* While dma channel is allocated, we only want the core irqs active
+ * for fault reports, otherwise we'd get irqs that we don't care about.
+ * Except for TX irqs, where dma done != fifo empty and reusable ...
+ *
+ * NOTE: docs don't say either way, but irq masking **enables** irqs.
+ *
+ * REVISIT same issue applies to pure PIO usage too, and non-cppi dma...
+ */
+static inline void core_rxirq_disable(void __iomem *tibase, unsigned epnum)
+{
+       musb_writel(tibase, DAVINCI_USB_INT_MASK_CLR_REG, 1 << (epnum + 8));
+}
+
+static inline void core_rxirq_enable(void __iomem *tibase, unsigned epnum)
+{
+       musb_writel(tibase, DAVINCI_USB_INT_MASK_SET_REG, 1 << (epnum + 8));
+}
+
+
+/*
+ * Allocate a CPPI Channel for DMA.  With CPPI, channels are bound to
+ * each transfer direction of a non-control endpoint, so allocating
+ * (and deallocating) is mostly a way to notice bad housekeeping on
+ * the software side.  We assume the irqs are always active.
+ */
+static struct dma_channel *
+cppi_channel_allocate(struct dma_controller *c,
+               struct musb_hw_ep *ep, u8 transmit)
+{
+       struct cppi             *controller;
+       u8                      index;
+       struct cppi_channel     *cppi_ch;
+       void __iomem            *tibase;
+
+       controller = container_of(c, struct cppi, controller);
+       tibase = controller->tibase;
+
+       /* ep0 doesn't use DMA; remember cppi indices are 0..N-1 */
+       index = ep->epnum - 1;
+
+       /* return the corresponding CPPI Channel Handle, and
+        * probably disable the non-CPPI irq until we need it.
+        */
+       if (transmit) {
+               if (index >= ARRAY_SIZE(controller->tx)) {
+                       DBG(1, "no %cX%d CPPI channel\n", 'T', index);
+                       return NULL;
+               }
+               cppi_ch = controller->tx + index;
+       } else {
+               if (index >= ARRAY_SIZE(controller->rx)) {
+                       DBG(1, "no %cX%d CPPI channel\n", 'R', index);
+                       return NULL;
+               }
+               cppi_ch = controller->rx + index;
+               core_rxirq_disable(tibase, ep->epnum);
+       }
+
+       /* REVISIT make this an error later once the same driver code works
+        * with the other DMA engine too
+        */
+       if (cppi_ch->hw_ep)
+               DBG(1, "re-allocating DMA%d %cX channel %p\n",
+                               index, transmit ? 'T' : 'R', cppi_ch);
+       cppi_ch->hw_ep = ep;
+       cppi_ch->channel.status = MUSB_DMA_STATUS_FREE;
+
+       DBG(4, "Allocate CPPI%d %cX\n", index, transmit ? 'T' : 'R');
+       return &cppi_ch->channel;
+}
+
+/* Release a CPPI Channel.  */
+static void cppi_channel_release(struct dma_channel *channel)
+{
+       struct cppi_channel     *c;
+       void __iomem            *tibase;
+
+       /* REVISIT:  for paranoia, check state and abort if needed... */
+
+       c = container_of(channel, struct cppi_channel, channel);
+       tibase = c->controller->tibase;
+       if (!c->hw_ep)
+               DBG(1, "releasing idle DMA channel %p\n", c);
+       else if (!c->transmit)
+               core_rxirq_enable(tibase, c->index + 1);
+
+       /* for now, leave its cppi IRQ enabled (we won't trigger it) */
+       c->hw_ep = NULL;
+       channel->status = MUSB_DMA_STATUS_UNKNOWN;
+}
+
+/* Context: controller irqlocked */
+static void
+cppi_dump_rx(int level, struct cppi_channel *c, const char *tag)
+{
+       void __iomem                    *base = c->controller->mregs;
+       struct cppi_rx_stateram __iomem *rx = c->state_ram;
+
+       musb_ep_select(base, c->index + 1);
+
+       DBG(level, "RX DMA%d%s: %d left, csr %04x, "
+                       "%08x H%08x S%08x C%08x, "
+                       "B%08x L%08x %08x .. %08x"
+                       "\n",
+               c->index, tag,
+               musb_readl(c->controller->tibase,
+                       DAVINCI_RXCPPI_BUFCNT0_REG + 4 * c->index),
+               musb_readw(c->hw_ep->regs, MUSB_RXCSR),
+
+               musb_readl(&rx->rx_skipbytes, 0),
+               musb_readl(&rx->rx_head, 0),
+               musb_readl(&rx->rx_sop, 0),
+               musb_readl(&rx->rx_current, 0),
+
+               musb_readl(&rx->rx_buf_current, 0),
+               musb_readl(&rx->rx_len_len, 0),
+               musb_readl(&rx->rx_cnt_cnt, 0),
+               musb_readl(&rx->rx_complete, 0)
+               );
+}
+
+/* Context: controller irqlocked */
+static void
+cppi_dump_tx(int level, struct cppi_channel *c, const char *tag)
+{
+       void __iomem                    *base = c->controller->mregs;
+       struct cppi_tx_stateram __iomem *tx = c->state_ram;
+
+       musb_ep_select(base, c->index + 1);
+
+       DBG(level, "TX DMA%d%s: csr %04x, "
+                       "H%08x S%08x C%08x %08x, "
+                       "F%08x L%08x .. %08x"
+                       "\n",
+               c->index, tag,
+               musb_readw(c->hw_ep->regs, MUSB_TXCSR),
+
+               musb_readl(&tx->tx_head, 0),
+               musb_readl(&tx->tx_buf, 0),
+               musb_readl(&tx->tx_current, 0),
+               musb_readl(&tx->tx_buf_current, 0),
+
+               musb_readl(&tx->tx_info, 0),
+               musb_readl(&tx->tx_rem_len, 0),
+               /* dummy/unused word 6 */
+               musb_readl(&tx->tx_complete, 0)
+               );
+}
+
+/* Context: controller irqlocked */
+static inline void
+cppi_rndis_update(struct cppi_channel *c, int is_rx,
+               void __iomem *tibase, int is_rndis)
+{
+       /* we may need to change the rndis flag for this cppi channel */
+       if (c->is_rndis != is_rndis) {
+               u32     value = musb_readl(tibase, DAVINCI_RNDIS_REG);
+               u32     temp = 1 << (c->index);
+
+               if (is_rx)
+                       temp <<= 16;
+               if (is_rndis)
+                       value |= temp;
+               else
+                       value &= ~temp;
+               musb_writel(tibase, DAVINCI_RNDIS_REG, value);
+               c->is_rndis = is_rndis;
+       }
+}
+
+static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
+{
+       pr_debug("RXBD/%s %08x: "
+                       "nxt %08x buf %08x off.blen %08x opt.plen %08x\n",
+                       tag, bd->dma,
+                       bd->hw_next, bd->hw_bufp, bd->hw_off_len,
+                       bd->hw_options);
+}
+
+static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx)
+{
+#if MUSB_DEBUG > 0
+       struct cppi_descriptor  *bd;
+
+       if (!_dbg_level(level))
+               return;
+       cppi_dump_rx(level, rx, tag);
+       if (rx->last_processed)
+               cppi_dump_rxbd("last", rx->last_processed);
+       for (bd = rx->head; bd; bd = bd->next)
+               cppi_dump_rxbd("active", bd);
+#endif
+}
+
+
+/* NOTE:  DaVinci autoreq is ignored except for host side "RNDIS" mode RX;
+ * so we won't ever use it (see "CPPI RX Woes" below).
+ */
+static inline int cppi_autoreq_update(struct cppi_channel *rx,
+               void __iomem *tibase, int onepacket, unsigned n_bds)
+{
+       u32     val;
+
+#ifdef RNDIS_RX_IS_USABLE
+       u32     tmp;
+       /* assert(is_host_active(musb)) */
+
+       /* start from "AutoReq never" */
+       tmp = musb_readl(tibase, DAVINCI_AUTOREQ_REG);
+       val = tmp & ~((0x3) << (rx->index * 2));
+
+       /* HCD arranged reqpkt for packet #1.  we arrange int
+        * for all but the last one, maybe in two segments.
+        */
+       if (!onepacket) {
+#if 0
+               /* use two segments, autoreq "all" then the last "never" */
+               val |= ((0x3) << (rx->index * 2));
+               n_bds--;
+#else
+               /* one segment, autoreq "all-but-last" */
+               val |= ((0x1) << (rx->index * 2));
+#endif
+       }
+
+       if (val != tmp) {
+               int n = 100;
+
+               /* make sure that autoreq is updated before continuing */
+               musb_writel(tibase, DAVINCI_AUTOREQ_REG, val);
+               do {
+                       tmp = musb_readl(tibase, DAVINCI_AUTOREQ_REG);
+                       if (tmp == val)
+                               break;
+                       cpu_relax();
+               } while (n-- > 0);
+       }
+#endif
+
+       /* REQPKT is turned off after each segment */
+       if (n_bds && rx->channel.actual_len) {
+               void __iomem    *regs = rx->hw_ep->regs;
+
+               val = musb_readw(regs, MUSB_RXCSR);
+               if (!(val & MUSB_RXCSR_H_REQPKT)) {
+                       val |= MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_H_WZC_BITS;
+                       musb_writew(regs, MUSB_RXCSR, val);
+                       /* flush writebufer */
+                       val = musb_readw(regs, MUSB_RXCSR);
+               }
+       }
+       return n_bds;
+}
+
+
+/* Buffer enqueuing Logic:
+ *
+ *  - RX builds new queues each time, to help handle routine "early
+ *    termination" cases (faults, including errors and short reads)
+ *    more correctly.
+ *
+ *  - for now, TX reuses the same queue of BDs every time
+ *
+ * REVISIT long term, we want a normal dynamic model.
+ * ... the goal will be to append to the
+ * existing queue, processing completed "dma buffers" (segments) on the fly.
+ *
+ * Otherwise we force an IRQ latency between requests, which slows us a lot
+ * (especially in "transparent" dma).  Unfortunately that model seems to be
+ * inherent in the DMA model from the Mentor code, except in the rare case
+ * of transfers big enough (~128+ KB) that we could append "middle" segments
+ * in the TX paths.  (RX can't do this, see below.)
+ *
+ * That's true even in the CPPI- friendly iso case, where most urbs have
+ * several small segments provided in a group and where the "packet at a time"
+ * "transparent" DMA model is always correct, even on the RX side.
+ */
+
+/*
+ * CPPI TX:
+ * ========
+ * TX is a lot more reasonable than RX; it doesn't need to run in
+ * irq-per-packet mode very often.  RNDIS mode seems to behave too
+ * (except how it handles the exactly-N-packets case).  Building a
+ * txdma queue with multiple requests (urb or usb_request) looks
+ * like it would work ... but fault handling would need much testing.
+ *
+ * The main issue with TX mode RNDIS relates to transfer lengths that
+ * are an exact multiple of the packet length.  It appears that there's
+ * a hiccup in that case (maybe the DMA completes before the ZLP gets
+ * written?) boiling down to not being able to rely on CPPI writing any
+ * terminating zero length packet before the next transfer is written.
+ * So that's punted to PIO; better yet, gadget drivers can avoid it.
+ *
+ * Plus, there's allegedly an undocumented constraint that rndis transfer
+ * length be a multiple of 64 bytes ... but the chip doesn't act that
+ * way, and we really don't _want_ that behavior anyway.
+ *
+ * On TX, "transparent" mode works ... although experiments have shown
+ * problems trying to use the SOP/EOP bits in different USB packets.
+ *
+ * REVISIT try to handle terminating zero length packets using CPPI
+ * instead of doing it by PIO after an IRQ.  (Meanwhile, make Ethernet
+ * links avoid that issue by forcing them to avoid zlps.)
+ */
+static void
+cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx)
+{
+       unsigned                maxpacket = tx->maxpacket;
+       dma_addr_t              addr = tx->buf_dma + tx->offset;
+       size_t                  length = tx->buf_len - tx->offset;
+       struct cppi_descriptor  *bd;
+       unsigned                n_bds;
+       unsigned                i;
+       struct cppi_tx_stateram __iomem *tx_ram = tx->state_ram;
+       int                     rndis;
+
+       /* TX can use the CPPI "rndis" mode, where we can probably fit this
+        * transfer in one BD and one IRQ.  The only time we would NOT want
+        * to use it is when hardware constraints prevent it, or if we'd
+        * trigger the "send a ZLP?" confusion.
+        */
+       rndis = (maxpacket & 0x3f) == 0
+               && length < 0xffff
+               && (length % maxpacket) != 0;
+
+       if (rndis) {
+               maxpacket = length;
+               n_bds = 1;
+       } else {
+               n_bds = length / maxpacket;
+               if (!length || (length % maxpacket))
+                       n_bds++;
+               n_bds = min(n_bds, (unsigned) NUM_TXCHAN_BD);
+               length = min(n_bds * maxpacket, length);
+       }
+
+       DBG(4, "TX DMA%d, pktSz %d %s bds %d dma 0x%x len %u\n",
+                       tx->index,
+                       maxpacket,
+                       rndis ? "rndis" : "transparent",
+                       n_bds,
+                       addr, length);
+
+       cppi_rndis_update(tx, 0, musb->ctrl_base, rndis);
+
+       /* assuming here that channel_program is called during
+        * transfer initiation ... current code maintains state
+        * for one outstanding request only (no queues, not even
+        * the implicit ones of an iso urb).
+        */
+
+       bd = tx->freelist;
+       tx->head = bd;
+       tx->last_processed = NULL;
+
+       /* FIXME use BD pool like RX side does, and just queue
+        * the minimum number for this request.
+        */
+
+       /* Prepare queue of BDs first, then hand it to hardware.
+        * All BDs except maybe the last should be of full packet
+        * size; for RNDIS there _is_ only that last packet.
+        */
+       for (i = 0; i < n_bds; ) {
+               if (++i < n_bds && bd->next)
+                       bd->hw_next = bd->next->dma;
+               else
+                       bd->hw_next = 0;
+
+               bd->hw_bufp = tx->buf_dma + tx->offset;
+
+               /* FIXME set EOP only on the last packet,
+                * SOP only on the first ... avoid IRQs
+                */
+               if ((tx->offset + maxpacket) <= tx->buf_len) {
+                       tx->offset += maxpacket;
+                       bd->hw_off_len = maxpacket;
+                       bd->hw_options = CPPI_SOP_SET | CPPI_EOP_SET
+                               | CPPI_OWN_SET | maxpacket;
+               } else {
+                       /* only this one may be a partial USB Packet */
+                       u32             partial_len;
+
+                       partial_len = tx->buf_len - tx->offset;
+                       tx->offset = tx->buf_len;
+                       bd->hw_off_len = partial_len;
+
+                       bd->hw_options = CPPI_SOP_SET | CPPI_EOP_SET
+                               | CPPI_OWN_SET | partial_len;
+                       if (partial_len == 0)
+                               bd->hw_options |= CPPI_ZERO_SET;
+               }
+
+               DBG(5, "TXBD %p: nxt %08x buf %08x len %04x opt %08x\n",
+                               bd, bd->hw_next, bd->hw_bufp,
+                               bd->hw_off_len, bd->hw_options);
+
+               /* update the last BD enqueued to the list */
+               tx->tail = bd;
+               bd = bd->next;
+       }
+
+       /* BDs live in DMA-coherent memory, but writes might be pending */
+       cpu_drain_writebuffer();
+
+       /* Write to the HeadPtr in state RAM to trigger */
+       musb_writel(&tx_ram->tx_head, 0, (u32)tx->freelist->dma);
+
+       cppi_dump_tx(5, tx, "/S");
+}
+
+/*
+ * CPPI RX Woes:
+ * =============
+ * Consider a 1KB bulk RX buffer in two scenarios:  (a) it's fed two 300 byte
+ * packets back-to-back, and (b) it's fed two 512 byte packets back-to-back.
+ * (Full speed transfers have similar scenarios.)
+ *
+ * The correct behavior for Linux is that (a) fills the buffer with 300 bytes,
+ * and the next packet goes into a buffer that's queued later; while (b) fills
+ * the buffer with 1024 bytes.  How to do that with CPPI?
+ *
+ * - RX queues in "rndis" mode -- one single BD -- handle (a) correctly, but
+ *   (b) loses **BADLY** because nothing (!) happens when that second packet
+ *   fills the buffer, much less when a third one arrives.  (Which makes this
+ *   not a "true" RNDIS mode.  In the RNDIS protocol short-packet termination
+ *   is optional, and it's fine if peripherals -- not hosts! -- pad messages
+ *   out to end-of-buffer.  Standard PCI host controller DMA descriptors
+ *   implement that mode by default ... which is no accident.)
+ *
+ * - RX queues in "transparent" mode -- two BDs with 512 bytes each -- have
+ *   converse problems:  (b) is handled right, but (a) loses badly.  CPPI RX
+ *   ignores SOP/EOP markings and processes both of those BDs; so both packets
+ *   are loaded into the buffer (with a 212 byte gap between them), and the next
+ *   buffer queued will NOT get its 300 bytes of data. (It seems like SOP/EOP
+ *   are intended as outputs for RX queues, not inputs...)
+ *
+ * - A variant of "transparent" mode -- one BD at a time -- is the only way to
+ *   reliably make both cases work, with software handling both cases correctly
+ *   and at the significant penalty of needing an IRQ per packet.  (The lack of
+ *   I/O overlap can be slightly ameliorated by enabling double buffering.)
+ *
+ * So how to get rid of IRQ-per-packet?  The transparent multi-BD case could
+ * be used in special cases like mass storage, which sets URB_SHORT_NOT_OK
+ * (or maybe its peripheral side counterpart) to flag (a) scenarios as errors
+ * with guaranteed driver level fault recovery and scrubbing out what's left
+ * of that garbaged datastream.
+ *
+ * But there seems to be no way to identify the cases where CPPI RNDIS mode
+ * is appropriate -- which do NOT include RNDIS host drivers, but do include
+ * the CDC Ethernet driver! -- and the documentation is incomplete/wrong.
+ * So we can't _ever_ use RX RNDIS mode ... except by using a heuristic
+ * that applies best on the peripheral side (and which could fail rudely).
+ *
+ * Leaving only "transparent" mode; we avoid multi-bd modes in almost all
+ * cases other than mass storage class.  Otherwise we're correct but slow,
+ * since CPPI penalizes our need for a "true RNDIS" default mode.
+ */
+
+
+/* Heuristic, intended to kick in for ethernet/rndis peripheral ONLY
+ *
+ * IFF
+ *  (a)        peripheral mode ... since rndis peripherals could pad their
+ *     writes to hosts, causing i/o failure; or we'd have to cope with
+ *     a largely unknowable variety of host side protocol variants
+ *  (b)        and short reads are NOT errors ... since full reads would
+ *     cause those same i/o failures
+ *  (c)        and read length is
+ *     - less than 64KB (max per cppi descriptor)
+ *     - not a multiple of 4096 (g_zero default, full reads typical)
+ *     - N (>1) packets long, ditto (full reads not EXPECTED)
+ * THEN
+ *   try rx rndis mode
+ *
+ * Cost of heuristic failing:  RXDMA wedges at the end of transfers that
+ * fill out the whole buffer.  Buggy host side usb network drivers could
+ * trigger that, but "in the field" such bugs seem to be all but unknown.
+ *
+ * So this module parameter lets the heuristic be disabled.  When using
+ * gadgetfs, the heuristic will probably need to be disabled.
+ */
+static int cppi_rx_rndis = 1;
+
+module_param(cppi_rx_rndis, bool, 0);
+MODULE_PARM_DESC(cppi_rx_rndis, "enable/disable RX RNDIS heuristic");
+
+
+/**
+ * cppi_next_rx_segment - dma read for the next chunk of a buffer
+ * @musb: the controller
+ * @rx: dma channel
+ * @onepacket: true unless caller treats short reads as errors, and
+ *     performs fault recovery above usbcore.
+ * Context: controller irqlocked
+ *
+ * See above notes about why we can't use multi-BD RX queues except in
+ * rare cases (mass storage class), and can never use the hardware "rndis"
+ * mode (since it's not a "true" RNDIS mode) with complete safety..
+ *
+ * It's ESSENTIAL that callers specify "onepacket" mode unless they kick in
+ * code to recover from corrupted datastreams after each short transfer.
+ */
+static void
+cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
+{
+       unsigned                maxpacket = rx->maxpacket;
+       dma_addr_t              addr = rx->buf_dma + rx->offset;
+       size_t                  length = rx->buf_len - rx->offset;
+       struct cppi_descriptor  *bd, *tail;
+       unsigned                n_bds;
+       unsigned                i;
+       void __iomem            *tibase = musb->ctrl_base;
+       int                     is_rndis = 0;
+       struct cppi_rx_stateram __iomem *rx_ram = rx->state_ram;
+
+       if (onepacket) {
+               /* almost every USB driver, host or peripheral side */
+               n_bds = 1;
+
+               /* maybe apply the heuristic above */
+               if (cppi_rx_rndis
+                               && is_peripheral_active(musb)
+                               && length > maxpacket
+                               && (length & ~0xffff) == 0
+                               && (length & 0x0fff) != 0
+                               && (length & (maxpacket - 1)) == 0) {
+                       maxpacket = length;
+                       is_rndis = 1;
+               }
+       } else {
+               /* virtually nothing except mass storage class */
+               if (length > 0xffff) {
+                       n_bds = 0xffff / maxpacket;
+                       length = n_bds * maxpacket;
+               } else {
+                       n_bds = length / maxpacket;
+                       if (length % maxpacket)
+                               n_bds++;
+               }
+               if (n_bds == 1)
+                       onepacket = 1;
+               else
+                       n_bds = min(n_bds, (unsigned) NUM_RXCHAN_BD);
+       }
+
+       /* In host mode, autorequest logic can generate some IN tokens; it's
+        * tricky since we can't leave REQPKT set in RXCSR after the transfer
+        * finishes. So:  multipacket transfers involve two or more segments.
+        * And always at least two IRQs ... RNDIS mode is not an option.
+        */
+       if (is_host_active(musb))
+               n_bds = cppi_autoreq_update(rx, tibase, onepacket, n_bds);
+
+       cppi_rndis_update(rx, 1, musb->ctrl_base, is_rndis);
+
+       length = min(n_bds * maxpacket, length);
+
+       DBG(4, "RX DMA%d seg, maxp %d %s bds %d (cnt %d) "
+                       "dma 0x%x len %u %u/%u\n",
+                       rx->index, maxpacket,
+                       onepacket
+                               ? (is_rndis ? "rndis" : "onepacket")
+                               : "multipacket",
+                       n_bds,
+                       musb_readl(tibase,
+                               DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4))
+                                       & 0xffff,
+                       addr, length, rx->channel.actual_len, rx->buf_len);
+
+       /* only queue one segment at a time, since the hardware prevents
+        * correct queue shutdown after unexpected short packets
+        */
+       bd = cppi_bd_alloc(rx);
+       rx->head = bd;
+
+       /* Build BDs for all packets in this segment */
+       for (i = 0, tail = NULL; bd && i < n_bds; i++, tail = bd) {
+               u32     bd_len;
+
+               if (i) {
+                       bd = cppi_bd_alloc(rx);
+                       if (!bd)
+                               break;
+                       tail->next = bd;
+                       tail->hw_next = bd->dma;
+               }
+               bd->hw_next = 0;
+
+               /* all but the last packet will be maxpacket size */
+               if (maxpacket < length)
+                       bd_len = maxpacket;
+               else
+                       bd_len = length;
+
+               bd->hw_bufp = addr;
+               addr += bd_len;
+               rx->offset += bd_len;
+
+               bd->hw_off_len = (0 /*offset*/ << 16) + bd_len;
+               bd->buflen = bd_len;
+
+               bd->hw_options = CPPI_OWN_SET | (i == 0 ? length : 0);
+               length -= bd_len;
+       }
+
+       /* we always expect at least one reusable BD! */
+       if (!tail) {
+               WARNING("rx dma%d -- no BDs? need %d\n", rx->index, n_bds);
+               return;
+       } else if (i < n_bds)
+               WARNING("rx dma%d -- only %d of %d BDs\n", rx->index, i, n_bds);
+
+       tail->next = NULL;
+       tail->hw_next = 0;
+
+       bd = rx->head;
+       rx->tail = tail;
+
+       /* short reads and other faults should terminate this entire
+        * dma segment.  we want one "dma packet" per dma segment, not
+        * one per USB packet, terminating the whole queue at once...
+        * NOTE that current hardware seems to ignore SOP and EOP.
+        */
+       bd->hw_options |= CPPI_SOP_SET;
+       tail->hw_options |= CPPI_EOP_SET;
+
+       if (debug >= 5) {
+               struct cppi_descriptor  *d;
+
+               for (d = rx->head; d; d = d->next)
+                       cppi_dump_rxbd("S", d);
+       }
+
+       /* in case the preceding transfer left some state... */
+       tail = rx->last_processed;
+       if (tail) {
+               tail->next = bd;
+               tail->hw_next = bd->dma;
+       }
+
+       core_rxirq_enable(tibase, rx->index + 1);
+
+       /* BDs live in DMA-coherent memory, but writes might be pending */
+       cpu_drain_writebuffer();
+
+       /* REVISIT specs say to write this AFTER the BUFCNT register
+        * below ... but that loses badly.
+        */
+       musb_writel(&rx_ram->rx_head, 0, bd->dma);
+
+       /* bufferCount must be at least 3, and zeroes on completion
+        * unless it underflows below zero, or stops at two, or keeps
+        * growing ... grr.
+        */
+       i = musb_readl(tibase,
+                       DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4))
+                       & 0xffff;
+
+       if (!i)
+               musb_writel(tibase,
+                       DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4),
+                       n_bds + 2);
+       else if (n_bds > (i - 3))
+               musb_writel(tibase,
+                       DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4),
+                       n_bds - (i - 3));
+
+       i = musb_readl(tibase,
+                       DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4))
+                       & 0xffff;
+       if (i < (2 + n_bds)) {
+               DBG(2, "bufcnt%d underrun - %d (for %d)\n",
+                                       rx->index, i, n_bds);
+               musb_writel(tibase,
+                       DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4),
+                       n_bds + 2);
+       }
+
+       cppi_dump_rx(4, rx, "/S");
+}
+
+/**
+ * cppi_channel_program - program channel for data transfer
+ * @ch: the channel
+ * @maxpacket: max packet size
+ * @mode: For RX, 1 unless the usb protocol driver promised to treat
+ *     all short reads as errors and kick in high level fault recovery.
+ *     For TX, ignored because of RNDIS mode races/glitches.
+ * @dma_addr: dma address of buffer
+ * @len: length of buffer
+ * Context: controller irqlocked
+ */
+static int cppi_channel_program(struct dma_channel *ch,
+               u16 maxpacket, u8 mode,
+               dma_addr_t dma_addr, u32 len)
+{
+       struct cppi_channel     *cppi_ch;
+       struct cppi             *controller;
+       struct musb             *musb;
+
+       cppi_ch = container_of(ch, struct cppi_channel, channel);
+       controller = cppi_ch->controller;
+       musb = controller->musb;
+
+       switch (ch->status) {
+       case MUSB_DMA_STATUS_BUS_ABORT:
+       case MUSB_DMA_STATUS_CORE_ABORT:
+               /* fault irq handler should have handled cleanup */
+               WARNING("%cX DMA%d not cleaned up after abort!\n",
+                               cppi_ch->transmit ? 'T' : 'R',
+                               cppi_ch->index);
+               /* WARN_ON(1); */
+               break;
+       case MUSB_DMA_STATUS_BUSY:
+               WARNING("program active channel?  %cX DMA%d\n",
+                               cppi_ch->transmit ? 'T' : 'R',
+                               cppi_ch->index);
+               /* WARN_ON(1); */
+               break;
+       case MUSB_DMA_STATUS_UNKNOWN:
+               DBG(1, "%cX DMA%d not allocated!\n",
+                               cppi_ch->transmit ? 'T' : 'R',
+                               cppi_ch->index);
+               /* FALLTHROUGH */
+       case MUSB_DMA_STATUS_FREE:
+               break;
+       }
+
+       ch->status = MUSB_DMA_STATUS_BUSY;
+
+       /* set transfer parameters, then queue up its first segment */
+       cppi_ch->buf_dma = dma_addr;
+       cppi_ch->offset = 0;
+       cppi_ch->maxpacket = maxpacket;
+       cppi_ch->buf_len = len;
+
+       /* TX channel? or RX? */
+       if (cppi_ch->transmit)
+               cppi_next_tx_segment(musb, cppi_ch);
+       else
+               cppi_next_rx_segment(musb, cppi_ch, mode);
+
+       return true;
+}
+
+static bool cppi_rx_scan(struct cppi *cppi, unsigned ch)
+{
+       struct cppi_channel             *rx = &cppi->rx[ch];
+       struct cppi_rx_stateram __iomem *state = rx->state_ram;
+       struct cppi_descriptor          *bd;
+       struct cppi_descriptor          *last = rx->last_processed;
+       bool                            completed = false;
+       bool                            acked = false;
+       int                             i;
+       dma_addr_t                      safe2ack;
+       void __iomem                    *regs = rx->hw_ep->regs;
+
+       cppi_dump_rx(6, rx, "/K");
+
+       bd = last ? last->next : rx->head;
+       if (!bd)
+               return false;
+
+       /* run through all completed BDs */
+       for (i = 0, safe2ack = musb_readl(&state->rx_complete, 0);
+                       (safe2ack || completed) && bd && i < NUM_RXCHAN_BD;
+                       i++, bd = bd->next) {
+               u16     len;
+
+               /* catch latest BD writes from CPPI */
+               rmb();
+               if (!completed && (bd->hw_options & CPPI_OWN_SET))
+                       break;
+
+               DBG(5, "C/RXBD %08x: nxt %08x buf %08x "
+                       "off.len %08x opt.len %08x (%d)\n",
+                       bd->dma, bd->hw_next, bd->hw_bufp,
+                       bd->hw_off_len, bd->hw_options,
+                       rx->channel.actual_len);
+
+               /* actual packet received length */
+               if ((bd->hw_options & CPPI_SOP_SET) && !completed)
+                       len = bd->hw_off_len & CPPI_RECV_PKTLEN_MASK;
+               else
+                       len = 0;
+
+               if (bd->hw_options & CPPI_EOQ_MASK)
+                       completed = true;
+
+               if (!completed && len < bd->buflen) {
+                       /* NOTE:  when we get a short packet, RXCSR_H_REQPKT
+                        * must have been cleared, and no more DMA packets may
+                        * active be in the queue... TI docs didn't say, but
+                        * CPPI ignores those BDs even though OWN is still set.
+                        */
+                       completed = true;
+                       DBG(3, "rx short %d/%d (%d)\n",
+                                       len, bd->buflen,
+                                       rx->channel.actual_len);
+               }
+
+               /* If we got here, we expect to ack at least one BD; meanwhile
+                * CPPI may completing other BDs while we scan this list...
+                *
+                * RACE: we can notice OWN cleared before CPPI raises the
+                * matching irq by writing that BD as the completion pointer.
+                * In such cases, stop scanning and wait for the irq, avoiding
+                * lost acks and states where BD ownership is unclear.
+                */
+               if (bd->dma == safe2ack) {
+                       musb_writel(&state->rx_complete, 0, safe2ack);
+                       safe2ack = musb_readl(&state->rx_complete, 0);
+                       acked = true;
+                       if (bd->dma == safe2ack)
+                               safe2ack = 0;
+               }
+
+               rx->channel.actual_len += len;
+
+               cppi_bd_free(rx, last);
+               last = bd;
+
+               /* stop scanning on end-of-segment */
+               if (bd->hw_next == 0)
+                       completed = true;
+       }
+       rx->last_processed = last;
+
+       /* dma abort, lost ack, or ... */
+       if (!acked && last) {
+               int     csr;
+
+               if (safe2ack == 0 || safe2ack == rx->last_processed->dma)
+                       musb_writel(&state->rx_complete, 0, safe2ack);
+               if (safe2ack == 0) {
+                       cppi_bd_free(rx, last);
+                       rx->last_processed = NULL;
+
+                       /* if we land here on the host side, H_REQPKT will
+                        * be clear and we need to restart the queue...
+                        */
+                       WARN_ON(rx->head);
+               }
+               musb_ep_select(cppi->mregs, rx->index + 1);
+               csr = musb_readw(regs, MUSB_RXCSR);
+               if (csr & MUSB_RXCSR_DMAENAB) {
+                       DBG(4, "list%d %p/%p, last %08x%s, csr %04x\n",
+                               rx->index,
+                               rx->head, rx->tail,
+                               rx->last_processed
+                                       ? rx->last_processed->dma
+                                       : 0,
+                               completed ? ", completed" : "",
+                               csr);
+                       cppi_dump_rxq(4, "/what?", rx);
+               }
+       }
+       if (!completed) {
+               int     csr;
+
+               rx->head = bd;
+
+               /* REVISIT seems like "autoreq all but EOP" doesn't...
+                * setting it here "should" be racey, but seems to work
+                */
+               csr = musb_readw(rx->hw_ep->regs, MUSB_RXCSR);
+               if (is_host_active(cppi->musb)
+                               && bd
+                               && !(csr & MUSB_RXCSR_H_REQPKT)) {
+                       csr |= MUSB_RXCSR_H_REQPKT;
+                       musb_writew(regs, MUSB_RXCSR,
+                                       MUSB_RXCSR_H_WZC_BITS | csr);
+                       csr = musb_readw(rx->hw_ep->regs, MUSB_RXCSR);
+               }
+       } else {
+               rx->head = NULL;
+               rx->tail = NULL;
+       }
+
+       cppi_dump_rx(6, rx, completed ? "/completed" : "/cleaned");
+       return completed;
+}
+
+void cppi_completion(struct musb *musb, u32 rx, u32 tx)
+{
+       void __iomem            *tibase;
+       int                     i, index;
+       struct cppi             *cppi;
+       struct musb_hw_ep       *hw_ep = NULL;
+
+       cppi = container_of(musb->dma_controller, struct cppi, controller);
+
+       tibase = musb->ctrl_base;
+
+       /* process TX channels */
+       for (index = 0; tx; tx = tx >> 1, index++) {
+               struct cppi_channel             *tx_ch;
+               struct cppi_tx_stateram __iomem *tx_ram;
+               bool                            completed = false;
+               struct cppi_descriptor          *bd;
+
+               if (!(tx & 1))
+                       continue;
+
+               tx_ch = cppi->tx + index;
+               tx_ram = tx_ch->state_ram;
+
+               /* FIXME  need a cppi_tx_scan() routine, which
+                * can also be called from abort code
+                */
+
+               cppi_dump_tx(5, tx_ch, "/E");
+
+               bd = tx_ch->head;
+
+               if (NULL == bd) {
+                       DBG(1, "null BD\n");
+                       continue;
+               }
+
+               /* run through all completed BDs */
+               for (i = 0; !completed && bd && i < NUM_TXCHAN_BD;
+                               i++, bd = bd->next) {
+                       u16     len;
+
+                       /* catch latest BD writes from CPPI */
+                       rmb();
+                       if (bd->hw_options & CPPI_OWN_SET)
+                               break;
+
+                       DBG(5, "C/TXBD %p n %x b %x off %x opt %x\n",
+                                       bd, bd->hw_next, bd->hw_bufp,
+                                       bd->hw_off_len, bd->hw_options);
+
+                       len = bd->hw_off_len & CPPI_BUFFER_LEN_MASK;
+                       tx_ch->channel.actual_len += len;
+
+                       tx_ch->last_processed = bd;
+
+                       /* write completion register to acknowledge
+                        * processing of completed BDs, and possibly
+                        * release the IRQ; EOQ might not be set ...
+                        *
+                        * REVISIT use the same ack strategy as rx
+                        *
+                        * REVISIT have observed bit 18 set; huh??
+                        */
+                       /* if ((bd->hw_options & CPPI_EOQ_MASK)) */
+                               musb_writel(&tx_ram->tx_complete, 0, bd->dma);
+
+                       /* stop scanning on end-of-segment */
+                       if (bd->hw_next == 0)
+                               completed = true;
+               }
+
+               /* on end of segment, maybe go to next one */
+               if (completed) {
+                       /* cppi_dump_tx(4, tx_ch, "/complete"); */
+
+                       /* transfer more, or report completion */
+                       if (tx_ch->offset >= tx_ch->buf_len) {
+                               tx_ch->head = NULL;
+                               tx_ch->tail = NULL;
+                               tx_ch->channel.status = MUSB_DMA_STATUS_FREE;
+
+                               hw_ep = tx_ch->hw_ep;
+
+                               /* Peripheral role never repurposes the
+                                * endpoint, so immediate completion is
+                                * safe.  Host role waits for the fifo
+                                * to empty (TXPKTRDY irq) before going
+                                * to the next queued bulk transfer.
+                                */
+                               if (is_host_active(cppi->musb)) {
+#if 0
+                                       /* WORKAROUND because we may
+                                        * not always get TXKPTRDY ...
+                                        */
+                                       int     csr;
+
+                                       csr = musb_readw(hw_ep->regs,
+                                               MUSB_TXCSR);
+                                       if (csr & MUSB_TXCSR_TXPKTRDY)
+#endif
+                                               completed = false;
+                               }
+                               if (completed)
+                                       musb_dma_completion(musb, index + 1, 1);
+
+                       } else {
+                               /* Bigger transfer than we could fit in
+                                * that first batch of descriptors...
+                                */
+                               cppi_next_tx_segment(musb, tx_ch);
+                       }
+               } else
+                       tx_ch->head = bd;
+       }
+
+       /* Start processing the RX block */
+       for (index = 0; rx; rx = rx >> 1, index++) {
+
+               if (rx & 1) {
+                       struct cppi_channel             *rx_ch;
+
+                       rx_ch = cppi->rx + index;
+
+                       /* let incomplete dma segments finish */
+                       if (!cppi_rx_scan(cppi, index))
+                               continue;
+
+                       /* start another dma segment if needed */
+                       if (rx_ch->channel.actual_len != rx_ch->buf_len
+                                       && rx_ch->channel.actual_len
+                                               == rx_ch->offset) {
+                               cppi_next_rx_segment(musb, rx_ch, 1);
+                               continue;
+                       }
+
+                       /* all segments completed! */
+                       rx_ch->channel.status = MUSB_DMA_STATUS_FREE;
+
+                       hw_ep = rx_ch->hw_ep;
+
+                       core_rxirq_disable(tibase, index + 1);
+                       musb_dma_completion(musb, index + 1, 0);
+               }
+       }
+
+       /* write to CPPI EOI register to re-enable interrupts */
+       musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0);
+}
+
+/* Instantiate a software object representing a DMA controller. */
+struct dma_controller *__init
+dma_controller_create(struct musb *musb, void __iomem *mregs)
+{
+       struct cppi             *controller;
+
+       controller = kzalloc(sizeof *controller, GFP_KERNEL);
+       if (!controller)
+               return NULL;
+
+       controller->mregs = mregs;
+       controller->tibase = mregs - DAVINCI_BASE_OFFSET;
+
+       controller->musb = musb;
+       controller->controller.start = cppi_controller_start;
+       controller->controller.stop = cppi_controller_stop;
+       controller->controller.channel_alloc = cppi_channel_allocate;
+       controller->controller.channel_release = cppi_channel_release;
+       controller->controller.channel_program = cppi_channel_program;
+       controller->controller.channel_abort = cppi_channel_abort;
+
+       /* NOTE: allocating from on-chip SRAM would give the least
+        * contention for memory access, if that ever matters here.
+        */
+
+       /* setup BufferPool */
+       controller->pool = dma_pool_create("cppi",
+                       controller->musb->controller,
+                       sizeof(struct cppi_descriptor),
+                       CPPI_DESCRIPTOR_ALIGN, 0);
+       if (!controller->pool) {
+               kfree(controller);
+               return NULL;
+       }
+
+       return &controller->controller;
+}
+
+/*
+ *  Destroy a previously-instantiated DMA controller.
+ */
+void dma_controller_destroy(struct dma_controller *c)
+{
+       struct cppi     *cppi;
+
+       cppi = container_of(c, struct cppi, controller);
+
+       /* assert:  caller stopped the controller first */
+       dma_pool_destroy(cppi->pool);
+
+       kfree(cppi);
+}
+
+/*
+ * Context: controller irqlocked, endpoint selected
+ */
+static int cppi_channel_abort(struct dma_channel *channel)
+{
+       struct cppi_channel     *cppi_ch;
+       struct cppi             *controller;
+       void __iomem            *mbase;
+       void __iomem            *tibase;
+       void __iomem            *regs;
+       u32                     value;
+       struct cppi_descriptor  *queue;
+
+       cppi_ch = container_of(channel, struct cppi_channel, channel);
+
+       controller = cppi_ch->controller;
+
+       switch (channel->status) {
+       case MUSB_DMA_STATUS_BUS_ABORT:
+       case MUSB_DMA_STATUS_CORE_ABORT:
+               /* from RX or TX fault irq handler */
+       case MUSB_DMA_STATUS_BUSY:
+               /* the hardware needs shutting down */
+               regs = cppi_ch->hw_ep->regs;
+               break;
+       case MUSB_DMA_STATUS_UNKNOWN:
+       case MUSB_DMA_STATUS_FREE:
+               return 0;
+       default:
+               return -EINVAL;
+       }
+
+       if (!cppi_ch->transmit && cppi_ch->head)
+               cppi_dump_rxq(3, "/abort", cppi_ch);
+
+       mbase = controller->mregs;
+       tibase = controller->tibase;
+
+       queue = cppi_ch->head;
+       cppi_ch->head = NULL;
+       cppi_ch->tail = NULL;
+
+       /* REVISIT should rely on caller having done this,
+        * and caller should rely on us not changing it.
+        * peripheral code is safe ... check host too.
+        */
+       musb_ep_select(mbase, cppi_ch->index + 1);
+
+       if (cppi_ch->transmit) {
+               struct cppi_tx_stateram __iomem *tx_ram;
+               int                     enabled;
+
+               /* mask interrupts raised to signal teardown complete.  */
+               enabled = musb_readl(tibase, DAVINCI_TXCPPI_INTENAB_REG)
+                               & (1 << cppi_ch->index);
+               if (enabled)
+                       musb_writel(tibase, DAVINCI_TXCPPI_INTCLR_REG,
+                                       (1 << cppi_ch->index));
+
+               /* REVISIT put timeouts on these controller handshakes */
+
+               cppi_dump_tx(6, cppi_ch, " (teardown)");
+
+               /* teardown DMA engine then usb core */
+               do {
+                       value = musb_readl(tibase, DAVINCI_TXCPPI_TEAR_REG);
+               } while (!(value & CPPI_TEAR_READY));
+               musb_writel(tibase, DAVINCI_TXCPPI_TEAR_REG, cppi_ch->index);
+
+               tx_ram = cppi_ch->state_ram;
+               do {
+                       value = musb_readl(&tx_ram->tx_complete, 0);
+               } while (0xFFFFFFFC != value);
+               musb_writel(&tx_ram->tx_complete, 0, 0xFFFFFFFC);
+
+               /* FIXME clean up the transfer state ... here?
+                * the completion routine should get called with
+                * an appropriate status code.
+                */
+
+               value = musb_readw(regs, MUSB_TXCSR);
+               value &= ~MUSB_TXCSR_DMAENAB;
+               value |= MUSB_TXCSR_FLUSHFIFO;
+               musb_writew(regs, MUSB_TXCSR, value);
+               musb_writew(regs, MUSB_TXCSR, value);
+
+               /* re-enable interrupt */
+               if (enabled)
+                       musb_writel(tibase, DAVINCI_TXCPPI_INTENAB_REG,
+                                       (1 << cppi_ch->index));
+
+               /* While we scrub the TX state RAM, ensure that we clean
+                * up any interrupt that's currently asserted:
+                * 1. Write to completion Ptr value 0x1(bit 0 set)
+                *    (write back mode)
+                * 2. Write to completion Ptr value 0x0(bit 0 cleared)
+                *    (compare mode)
+                * Value written is compared(for bits 31:2) and when
+                * equal, interrupt is deasserted.
+                */
+               cppi_reset_tx(tx_ram, 1);
+               musb_writel(&tx_ram->tx_complete, 0, 0);
+
+               cppi_dump_tx(5, cppi_ch, " (done teardown)");
+
+               /* REVISIT tx side _should_ clean up the same way
+                * as the RX side ... this does no cleanup at all!
+                */
+
+       } else /* RX */ {
+               u16                     csr;
+
+               /* NOTE: docs don't guarantee any of this works ...  we
+                * expect that if the usb core stops telling the cppi core
+                * to pull more data from it, then it'll be safe to flush
+                * current RX DMA state iff any pending fifo transfer is done.
+                */
+
+               core_rxirq_disable(tibase, cppi_ch->index + 1);
+
+               /* for host, ensure ReqPkt is never set again */
+               if (is_host_active(cppi_ch->controller->musb)) {
+                       value = musb_readl(tibase, DAVINCI_AUTOREQ_REG);
+                       value &= ~((0x3) << (cppi_ch->index * 2));
+                       musb_writel(tibase, DAVINCI_AUTOREQ_REG, value);
+               }
+
+               csr = musb_readw(regs, MUSB_RXCSR);
+
+               /* for host, clear (just) ReqPkt at end of current packet(s) */
+               if (is_host_active(cppi_ch->controller->musb)) {
+                       csr |= MUSB_RXCSR_H_WZC_BITS;
+                       csr &= ~MUSB_RXCSR_H_REQPKT;
+               } else
+                       csr |= MUSB_RXCSR_P_WZC_BITS;
+
+               /* clear dma enable */
+               csr &= ~(MUSB_RXCSR_DMAENAB);
+               musb_writew(regs, MUSB_RXCSR, csr);
+               csr = musb_readw(regs, MUSB_RXCSR);
+
+               /* Quiesce: wait for current dma to finish (if not cleanup).
+                * We can't use bit zero of stateram->rx_sop, since that
+                * refers to an entire "DMA packet" not just emptying the
+                * current fifo.  Most segments need multiple usb packets.
+                */
+               if (channel->status == MUSB_DMA_STATUS_BUSY)
+                       udelay(50);
+
+               /* scan the current list, reporting any data that was
+                * transferred and acking any IRQ
+                */
+               cppi_rx_scan(controller, cppi_ch->index);
+
+               /* clobber the existing state once it's idle
+                *
+                * NOTE:  arguably, we should also wait for all the other
+                * RX channels to quiesce (how??) and then temporarily
+                * disable RXCPPI_CTRL_REG ... but it seems that we can
+                * rely on the controller restarting from state ram, with
+                * only RXCPPI_BUFCNT state being bogus.  BUFCNT will
+                * correct itself after the next DMA transfer though.
+                *
+                * REVISIT does using rndis mode change that?
+                */
+               cppi_reset_rx(cppi_ch->state_ram);
+
+               /* next DMA request _should_ load cppi head ptr */
+
+               /* ... we don't "free" that list, only mutate it in place.  */
+               cppi_dump_rx(5, cppi_ch, " (done abort)");
+
+               /* clean up previously pending bds */
+               cppi_bd_free(cppi_ch, cppi_ch->last_processed);
+               cppi_ch->last_processed = NULL;
+
+               while (queue) {
+                       struct cppi_descriptor  *tmp = queue->next;
+
+                       cppi_bd_free(cppi_ch, queue);
+                       queue = tmp;
+               }
+       }
+
+       channel->status = MUSB_DMA_STATUS_FREE;
+       cppi_ch->buf_dma = 0;
+       cppi_ch->offset = 0;
+       cppi_ch->buf_len = 0;
+       cppi_ch->maxpacket = 0;
+       return 0;
+}
+
+/* TBD Queries:
+ *
+ * Power Management ... probably turn off cppi during suspend, restart;
+ * check state ram?  Clocking is presumably shared with usb core.
+ */
diff --git a/drivers/usb/musb/cppi_dma.h b/drivers/usb/musb/cppi_dma.h
new file mode 100644 (file)
index 0000000..fc5216b
--- /dev/null
@@ -0,0 +1,133 @@
+/* Copyright (C) 2005-2006 by Texas Instruments */
+
+#ifndef _CPPI_DMA_H_
+#define _CPPI_DMA_H_
+
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/dmapool.h>
+
+#include "musb_dma.h"
+#include "musb_core.h"
+
+
+/* FIXME fully isolate CPPI from DaVinci ... the "CPPI generic" registers
+ * would seem to be shared with the TUSB6020 (over VLYNQ).
+ */
+
+#include "davinci.h"
+
+
+/* CPPI RX/TX state RAM */
+
+struct cppi_tx_stateram {
+       u32 tx_head;                    /* "DMA packet" head descriptor */
+       u32 tx_buf;
+       u32 tx_current;                 /* current descriptor */
+       u32 tx_buf_current;
+       u32 tx_info;                    /* flags, remaining buflen */
+       u32 tx_rem_len;
+       u32 tx_dummy;                   /* unused */
+       u32 tx_complete;
+};
+
+struct cppi_rx_stateram {
+       u32 rx_skipbytes;
+       u32 rx_head;
+       u32 rx_sop;                     /* "DMA packet" head descriptor */
+       u32 rx_current;                 /* current descriptor */
+       u32 rx_buf_current;
+       u32 rx_len_len;
+       u32 rx_cnt_cnt;
+       u32 rx_complete;
+};
+
+/* hw_options bits in CPPI buffer descriptors */
+#define CPPI_SOP_SET   ((u32)(1 << 31))
+#define CPPI_EOP_SET   ((u32)(1 << 30))
+#define CPPI_OWN_SET   ((u32)(1 << 29))        /* owned by cppi */
+#define CPPI_EOQ_MASK  ((u32)(1 << 28))
+#define CPPI_ZERO_SET  ((u32)(1 << 23))        /* rx saw zlp; tx issues one */
+#define CPPI_RXABT_MASK        ((u32)(1 << 19))        /* need more rx buffers */
+
+#define CPPI_RECV_PKTLEN_MASK 0xFFFF
+#define CPPI_BUFFER_LEN_MASK 0xFFFF
+
+#define CPPI_TEAR_READY ((u32)(1 << 31))
+
+/* CPPI data structure definitions */
+
+#define        CPPI_DESCRIPTOR_ALIGN   16      /* bytes; 5-dec docs say 4-byte align */
+
+struct cppi_descriptor {
+       /* hardware overlay */
+       u32             hw_next;        /* next buffer descriptor Pointer */
+       u32             hw_bufp;        /* i/o buffer pointer */
+       u32             hw_off_len;     /* buffer_offset16, buffer_length16 */
+       u32             hw_options;     /* flags:  SOP, EOP etc*/
+
+       struct cppi_descriptor *next;
+       dma_addr_t      dma;            /* address of this descriptor */
+       u32             buflen;         /* for RX: original buffer length */
+} __attribute__ ((aligned(CPPI_DESCRIPTOR_ALIGN)));
+
+
+struct cppi;
+
+/* CPPI  Channel Control structure */
+struct cppi_channel {
+       struct dma_channel      channel;
+
+       /* back pointer to the DMA controller structure */
+       struct cppi             *controller;
+
+       /* which direction of which endpoint? */
+       struct musb_hw_ep       *hw_ep;
+       bool                    transmit;
+       u8                      index;
+
+       /* DMA modes:  RNDIS or "transparent" */
+       u8                      is_rndis;
+
+       /* book keeping for current transfer request */
+       dma_addr_t              buf_dma;
+       u32                     buf_len;
+       u32                     maxpacket;
+       u32                     offset;         /* dma requested */
+
+       void __iomem            *state_ram;     /* CPPI state */
+
+       struct cppi_descriptor  *freelist;
+
+       /* BD management fields */
+       struct cppi_descriptor  *head;
+       struct cppi_descriptor  *tail;
+       struct cppi_descriptor  *last_processed;
+
+       /* use tx_complete in host role to track endpoints waiting for
+        * FIFONOTEMPTY to clear.
+        */
+       struct list_head        tx_complete;
+};
+
+/* CPPI DMA controller object */
+struct cppi {
+       struct dma_controller           controller;
+       struct musb                     *musb;
+       void __iomem                    *mregs;         /* Mentor regs */
+       void __iomem                    *tibase;        /* TI/CPPI regs */
+
+       struct cppi_channel             tx[MUSB_C_NUM_EPT - 1];
+       struct cppi_channel             rx[MUSB_C_NUM_EPR - 1];
+
+       struct dma_pool                 *pool;
+
+       struct list_head                tx_complete;
+};
+
+/* irq handling hook */
+extern void cppi_completion(struct musb *, u32 rx, u32 tx);
+
+#endif                         /* end of ifndef _CPPI_DMA_H_ */
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
new file mode 100644 (file)
index 0000000..75baf18
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2005-2006 by Texas Instruments
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ *
+ * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/memory.h>
+#include <asm/arch/gpio.h>
+#include <asm/mach-types.h>
+
+#include "musb_core.h"
+
+#ifdef CONFIG_MACH_DAVINCI_EVM
+#include <asm/arch/i2c-client.h>
+#endif
+
+#include "davinci.h"
+#include "cppi_dma.h"
+
+
+/* REVISIT (PM) we should be able to keep the PHY in low power mode most
+ * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0
+ * and, when in host mode, autosuspending idle root ports... PHYPLLON
+ * (overriding SUSPENDM?) then likely needs to stay off.
+ */
+
+static inline void phy_on(void)
+{
+       /* start the on-chip PHY and its PLL */
+       __raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON,
+                       (void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR));
+       while ((__raw_readl((void __force __iomem *)
+                               IO_ADDRESS(USBPHY_CTL_PADDR))
+                       & USBPHY_PHYCLKGD) == 0)
+               cpu_relax();
+}
+
+static inline void phy_off(void)
+{
+       /* powerdown the on-chip PHY and its oscillator */
+       __raw_writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, (void __force __iomem *)
+                       IO_ADDRESS(USBPHY_CTL_PADDR));
+}
+
+static int dma_off = 1;
+
+void musb_platform_enable(struct musb *musb)
+{
+       u32     tmp, old, val;
+
+       /* workaround:  setup irqs through both register sets */
+       tmp = (musb->epmask & DAVINCI_USB_TX_ENDPTS_MASK)
+                       << DAVINCI_USB_TXINT_SHIFT;
+       musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp);
+       old = tmp;
+       tmp = (musb->epmask & (0xfffe & DAVINCI_USB_RX_ENDPTS_MASK))
+                       << DAVINCI_USB_RXINT_SHIFT;
+       musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp);
+       tmp |= old;
+
+       val = ~MUSB_INTR_SOF;
+       tmp |= ((val & 0x01ff) << DAVINCI_USB_USBINT_SHIFT);
+       musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp);
+
+       if (is_dma_capable() && !dma_off)
+               printk(KERN_WARNING "%s %s: dma not reactivated\n",
+                               __FILE__, __func__);
+       else
+               dma_off = 0;
+
+       /* force a DRVVBUS irq so we can start polling for ID change */
+       if (is_otg_enabled(musb))
+               musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG,
+                       DAVINCI_INTR_DRVVBUS << DAVINCI_USB_USBINT_SHIFT);
+}
+
+/*
+ * Disable the HDRC and flush interrupts
+ */
+void musb_platform_disable(struct musb *musb)
+{
+       /* because we don't set CTRLR.UINT, "important" to:
+        *  - not read/write INTRUSB/INTRUSBE
+        *  - (except during initial setup, as workaround)
+        *  - use INTSETR/INTCLRR instead
+        */
+       musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_CLR_REG,
+                         DAVINCI_USB_USBINT_MASK
+                       | DAVINCI_USB_TXINT_MASK
+                       | DAVINCI_USB_RXINT_MASK);
+       musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+       musb_writel(musb->ctrl_base, DAVINCI_USB_EOI_REG, 0);
+
+       if (is_dma_capable() && !dma_off)
+               WARNING("dma still active\n");
+}
+
+
+/* REVISIT it's not clear whether DaVinci can support full OTG.  */
+
+static int vbus_state = -1;
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+#define        portstate(stmt)         stmt
+#else
+#define        portstate(stmt)
+#endif
+
+
+/* VBUS SWITCHING IS BOARD-SPECIFIC */
+
+#ifdef CONFIG_MACH_DAVINCI_EVM
+#ifndef CONFIG_MACH_DAVINCI_EVM_OTG
+
+/* I2C operations are always synchronous, and require a task context.
+ * With unloaded systems, using the shared workqueue seems to suffice
+ * to satisfy the 100msec A_WAIT_VRISE timeout...
+ */
+static void evm_deferred_drvvbus(struct work_struct *ignored)
+{
+       davinci_i2c_expander_op(0x3a, USB_DRVVBUS, vbus_state);
+       vbus_state = !vbus_state;
+}
+static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus);
+
+#endif /* modified board */
+#endif /* EVM */
+
+static void davinci_source_power(struct musb *musb, int is_on, int immediate)
+{
+       if (is_on)
+               is_on = 1;
+
+       if (vbus_state == is_on)
+               return;
+       vbus_state = !is_on;            /* 0/1 vs "-1 == unknown/init" */
+
+#ifdef CONFIG_MACH_DAVINCI_EVM
+       if (machine_is_davinci_evm()) {
+#ifdef CONFIG_MACH_DAVINCI_EVM_OTG
+               /* modified EVM board switching VBUS with GPIO(6) not I2C
+                * NOTE:  PINMUX0.RGB888 (bit23) must be clear
+                */
+               if (is_on)
+                       gpio_set(GPIO(6));
+               else
+                       gpio_clear(GPIO(6));
+               immediate = 1;
+#else
+               if (immediate)
+                       davinci_i2c_expander_op(0x3a, USB_DRVVBUS, !is_on);
+               else
+                       schedule_work(&evm_vbus_work);
+#endif
+       }
+#endif
+       if (immediate)
+               vbus_state = is_on;
+}
+
+static void davinci_set_vbus(struct musb *musb, int is_on)
+{
+       WARN_ON(is_on && is_peripheral_active(musb));
+       davinci_source_power(musb, is_on, 0);
+}
+
+
+#define        POLL_SECONDS    2
+
+static struct timer_list otg_workaround;
+
+static void otg_timer(unsigned long _musb)
+{
+       struct musb             *musb = (void *)_musb;
+       void __iomem            *mregs = musb->mregs;
+       u8                      devctl;
+       unsigned long           flags;
+
+       /* We poll because DaVinci's won't expose several OTG-critical
+       * status change events (from the transceiver) otherwise.
+        */
+       devctl = musb_readb(mregs, MUSB_DEVCTL);
+       DBG(7, "poll devctl %02x (%s)\n", devctl, otg_state_string(musb));
+
+       spin_lock_irqsave(&musb->lock, flags);
+       switch (musb->xceiv.state) {
+       case OTG_STATE_A_WAIT_VFALL:
+               /* Wait till VBUS falls below SessionEnd (~0.2V); the 1.3 RTL
+                * seems to mis-handle session "start" otherwise (or in our
+                * case "recover"), in routine "VBUS was valid by the time
+                * VBUSERR got reported during enumeration" cases.
+                */
+               if (devctl & MUSB_DEVCTL_VBUS) {
+                       mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+                       break;
+               }
+               musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
+               musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG,
+                       MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT);
+               break;
+       case OTG_STATE_B_IDLE:
+               if (!is_peripheral_enabled(musb))
+                       break;
+
+               /* There's no ID-changed IRQ, so we have no good way to tell
+                * when to switch to the A-Default state machine (by setting
+                * the DEVCTL.SESSION flag).
+                *
+                * Workaround:  whenever we're in B_IDLE, try setting the
+                * session flag every few seconds.  If it works, ID was
+                * grounded and we're now in the A-Default state machine.
+                *
+                * NOTE setting the session flag is _supposed_ to trigger
+                * SRP, but clearly it doesn't.
+                */
+               musb_writeb(mregs, MUSB_DEVCTL,
+                               devctl | MUSB_DEVCTL_SESSION);
+               devctl = musb_readb(mregs, MUSB_DEVCTL);
+               if (devctl & MUSB_DEVCTL_BDEVICE)
+                       mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+               else
+                       musb->xceiv.state = OTG_STATE_A_IDLE;
+               break;
+       default:
+               break;
+       }
+       spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static irqreturn_t davinci_interrupt(int irq, void *__hci)
+{
+       unsigned long   flags;
+       irqreturn_t     retval = IRQ_NONE;
+       struct musb     *musb = __hci;
+       void __iomem    *tibase = musb->ctrl_base;
+       u32             tmp;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       /* NOTE: DaVinci shadows the Mentor IRQs.  Don't manage them through
+        * the Mentor registers (except for setup), use the TI ones and EOI.
+        *
+        * Docs describe irq "vector" registers asociated with the CPPI and
+        * USB EOI registers.  These hold a bitmask corresponding to the
+        * current IRQ, not an irq handler address.  Would using those bits
+        * resolve some of the races observed in this dispatch code??
+        */
+
+       /* CPPI interrupts share the same IRQ line, but have their own
+        * mask, state, "vector", and EOI registers.
+        */
+       if (is_cppi_enabled()) {
+               u32 cppi_tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG);
+               u32 cppi_rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG);
+
+               if (cppi_tx || cppi_rx) {
+                       DBG(4, "CPPI IRQ t%x r%x\n", cppi_tx, cppi_rx);
+                       cppi_completion(musb, cppi_rx, cppi_tx);
+                       retval = IRQ_HANDLED;
+               }
+       }
+
+       /* ack and handle non-CPPI interrupts */
+       tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG);
+       musb_writel(tibase, DAVINCI_USB_INT_SRC_CLR_REG, tmp);
+       DBG(4, "IRQ %08x\n", tmp);
+
+       musb->int_rx = (tmp & DAVINCI_USB_RXINT_MASK)
+                       >> DAVINCI_USB_RXINT_SHIFT;
+       musb->int_tx = (tmp & DAVINCI_USB_TXINT_MASK)
+                       >> DAVINCI_USB_TXINT_SHIFT;
+       musb->int_usb = (tmp & DAVINCI_USB_USBINT_MASK)
+                       >> DAVINCI_USB_USBINT_SHIFT;
+
+       /* DRVVBUS irqs are the only proxy we have (a very poor one!) for
+        * DaVinci's missing ID change IRQ.  We need an ID change IRQ to
+        * switch appropriately between halves of the OTG state machine.
+        * Managing DEVCTL.SESSION per Mentor docs requires we know its
+        * value, but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
+        * Also, DRVVBUS pulses for SRP (but not at 5V) ...
+        */
+       if (tmp & (DAVINCI_INTR_DRVVBUS << DAVINCI_USB_USBINT_SHIFT)) {
+               int     drvvbus = musb_readl(tibase, DAVINCI_USB_STAT_REG);
+               void __iomem *mregs = musb->mregs;
+               u8      devctl = musb_readb(mregs, MUSB_DEVCTL);
+               int     err = musb->int_usb & MUSB_INTR_VBUSERROR;
+
+               err = is_host_enabled(musb)
+                               && (musb->int_usb & MUSB_INTR_VBUSERROR);
+               if (err) {
+                       /* The Mentor core doesn't debounce VBUS as needed
+                        * to cope with device connect current spikes. This
+                        * means it's not uncommon for bus-powered devices
+                        * to get VBUS errors during enumeration.
+                        *
+                        * This is a workaround, but newer RTL from Mentor
+                        * seems to allow a better one: "re"starting sessions
+                        * without waiting (on EVM, a **long** time) for VBUS
+                        * to stop registering in devctl.
+                        */
+                       musb->int_usb &= ~MUSB_INTR_VBUSERROR;
+                       musb->xceiv.state = OTG_STATE_A_WAIT_VFALL;
+                       mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+                       WARNING("VBUS error workaround (delay coming)\n");
+               } else if (is_host_enabled(musb) && drvvbus) {
+                       musb->is_active = 1;
+                       MUSB_HST_MODE(musb);
+                       musb->xceiv.default_a = 1;
+                       musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
+                       portstate(musb->port1_status |= USB_PORT_STAT_POWER);
+                       del_timer(&otg_workaround);
+               } else {
+                       musb->is_active = 0;
+                       MUSB_DEV_MODE(musb);
+                       musb->xceiv.default_a = 0;
+                       musb->xceiv.state = OTG_STATE_B_IDLE;
+                       portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
+               }
+
+               /* NOTE:  this must complete poweron within 100 msec */
+               davinci_source_power(musb, drvvbus, 0);
+               DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
+                               drvvbus ? "on" : "off",
+                               otg_state_string(musb),
+                               err ? " ERROR" : "",
+                               devctl);
+               retval = IRQ_HANDLED;
+       }
+
+       if (musb->int_tx || musb->int_rx || musb->int_usb)
+               retval |= musb_interrupt(musb);
+
+       /* irq stays asserted until EOI is written */
+       musb_writel(tibase, DAVINCI_USB_EOI_REG, 0);
+
+       /* poll for ID change */
+       if (is_otg_enabled(musb)
+                       && musb->xceiv.state == OTG_STATE_B_IDLE)
+               mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       /* REVISIT we sometimes get unhandled IRQs
+        * (e.g. ep0).  not clear why...
+        */
+       if (retval != IRQ_HANDLED)
+               DBG(5, "unhandled? %08x\n", tmp);
+       return IRQ_HANDLED;
+}
+
+int __init musb_platform_init(struct musb *musb)
+{
+       void __iomem    *tibase = musb->ctrl_base;
+       u32             revision;
+
+       musb->mregs += DAVINCI_BASE_OFFSET;
+#if 0
+       /* REVISIT there's something odd about clocking, this
+        * didn't appear do the job ...
+        */
+       musb->clock = clk_get(pDevice, "usb");
+       if (IS_ERR(musb->clock))
+               return PTR_ERR(musb->clock);
+
+       status = clk_enable(musb->clock);
+       if (status < 0)
+               return -ENODEV;
+#endif
+
+       /* returns zero if e.g. not clocked */
+       revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
+       if (revision == 0)
+               return -ENODEV;
+
+       if (is_host_enabled(musb))
+               setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
+
+       musb->board_set_vbus = davinci_set_vbus;
+       davinci_source_power(musb, 0, 1);
+
+       /* reset the controller */
+       musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
+
+       /* start the on-chip PHY and its PLL */
+       phy_on();
+
+       msleep(5);
+
+       /* NOTE:  irqs are in mixed mode, not bypass to pure-musb */
+       pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n",
+               revision, __raw_readl((void __force __iomem *)
+                               IO_ADDRESS(USBPHY_CTL_PADDR)),
+               musb_readb(tibase, DAVINCI_USB_CTRL_REG));
+
+       musb->isr = davinci_interrupt;
+       return 0;
+}
+
+int musb_platform_exit(struct musb *musb)
+{
+       if (is_host_enabled(musb))
+               del_timer_sync(&otg_workaround);
+
+       davinci_source_power(musb, 0 /*off*/, 1);
+
+       /* delay, to avoid problems with module reload */
+       if (is_host_enabled(musb) && musb->xceiv.default_a) {
+               int     maxdelay = 30;
+               u8      devctl, warn = 0;
+
+               /* if there's no peripheral connected, this can take a
+                * long time to fall, especially on EVM with huge C133.
+                */
+               do {
+                       devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+                       if (!(devctl & MUSB_DEVCTL_VBUS))
+                               break;
+                       if ((devctl & MUSB_DEVCTL_VBUS) != warn) {
+                               warn = devctl & MUSB_DEVCTL_VBUS;
+                               DBG(1, "VBUS %d\n",
+                                       warn >> MUSB_DEVCTL_VBUS_SHIFT);
+                       }
+                       msleep(1000);
+                       maxdelay--;
+               } while (maxdelay > 0);
+
+               /* in OTG mode, another host might be connected */
+               if (devctl & MUSB_DEVCTL_VBUS)
+                       DBG(1, "VBUS off timeout (devctl %02x)\n", devctl);
+       }
+
+       phy_off();
+       return 0;
+}
diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h
new file mode 100644 (file)
index 0000000..7fb6238
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2005-2006 by Texas Instruments
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ */
+
+#ifndef __MUSB_HDRDF_H__
+#define __MUSB_HDRDF_H__
+
+/*
+ * DaVinci-specific definitions
+ */
+
+/* Integrated highspeed/otg PHY */
+#define        USBPHY_CTL_PADDR        (DAVINCI_SYSTEM_MODULE_BASE + 0x34)
+#define        USBPHY_PHYCLKGD         (1 << 8)
+#define        USBPHY_SESNDEN          (1 << 7)        /* v(sess_end) comparator */
+#define        USBPHY_VBDTCTEN         (1 << 6)        /* v(bus) comparator */
+#define        USBPHY_PHYPLLON         (1 << 4)        /* override pll suspend */
+#define        USBPHY_CLKO1SEL         (1 << 3)
+#define        USBPHY_OSCPDWN          (1 << 2)
+#define        USBPHY_PHYPDWN          (1 << 0)
+
+/* For now include usb OTG module registers here */
+#define DAVINCI_USB_VERSION_REG                0x00
+#define DAVINCI_USB_CTRL_REG           0x04
+#define DAVINCI_USB_STAT_REG           0x08
+#define DAVINCI_RNDIS_REG              0x10
+#define DAVINCI_AUTOREQ_REG            0x14
+#define DAVINCI_USB_INT_SOURCE_REG     0x20
+#define DAVINCI_USB_INT_SET_REG                0x24
+#define DAVINCI_USB_INT_SRC_CLR_REG    0x28
+#define DAVINCI_USB_INT_MASK_REG       0x2c
+#define DAVINCI_USB_INT_MASK_SET_REG   0x30
+#define DAVINCI_USB_INT_MASK_CLR_REG   0x34
+#define DAVINCI_USB_INT_SRC_MASKED_REG 0x38
+#define DAVINCI_USB_EOI_REG            0x3c
+#define DAVINCI_USB_EOI_INTVEC         0x40
+
+/* BEGIN CPPI-generic (?) */
+
+/* CPPI related registers */
+#define DAVINCI_TXCPPI_CTRL_REG                0x80
+#define DAVINCI_TXCPPI_TEAR_REG                0x84
+#define DAVINCI_CPPI_EOI_REG           0x88
+#define DAVINCI_CPPI_INTVEC_REG                0x8c
+#define DAVINCI_TXCPPI_MASKED_REG      0x90
+#define DAVINCI_TXCPPI_RAW_REG         0x94
+#define DAVINCI_TXCPPI_INTENAB_REG     0x98
+#define DAVINCI_TXCPPI_INTCLR_REG      0x9c
+
+#define DAVINCI_RXCPPI_CTRL_REG                0xC0
+#define DAVINCI_RXCPPI_MASKED_REG      0xD0
+#define DAVINCI_RXCPPI_RAW_REG         0xD4
+#define DAVINCI_RXCPPI_INTENAB_REG     0xD8
+#define DAVINCI_RXCPPI_INTCLR_REG      0xDC
+
+#define DAVINCI_RXCPPI_BUFCNT0_REG     0xE0
+#define DAVINCI_RXCPPI_BUFCNT1_REG     0xE4
+#define DAVINCI_RXCPPI_BUFCNT2_REG     0xE8
+#define DAVINCI_RXCPPI_BUFCNT3_REG     0xEC
+
+/* CPPI state RAM entries */
+#define DAVINCI_CPPI_STATERAM_BASE_OFFSET   0x100
+
+#define DAVINCI_TXCPPI_STATERAM_OFFSET(chnum) \
+       (DAVINCI_CPPI_STATERAM_BASE_OFFSET +       ((chnum) * 0x40))
+#define DAVINCI_RXCPPI_STATERAM_OFFSET(chnum) \
+       (DAVINCI_CPPI_STATERAM_BASE_OFFSET + 0x20 + ((chnum) * 0x40))
+
+/* CPPI masks */
+#define DAVINCI_DMA_CTRL_ENABLE                1
+#define DAVINCI_DMA_CTRL_DISABLE       0
+
+#define DAVINCI_DMA_ALL_CHANNELS_ENABLE        0xF
+#define DAVINCI_DMA_ALL_CHANNELS_DISABLE 0xF
+
+/* END CPPI-generic (?) */
+
+#define DAVINCI_USB_TX_ENDPTS_MASK     0x1f            /* ep0 + 4 tx */
+#define DAVINCI_USB_RX_ENDPTS_MASK     0x1e            /* 4 rx */
+
+#define DAVINCI_USB_USBINT_SHIFT       16
+#define DAVINCI_USB_TXINT_SHIFT                0
+#define DAVINCI_USB_RXINT_SHIFT                8
+
+#define DAVINCI_INTR_DRVVBUS           0x0100
+
+#define DAVINCI_USB_USBINT_MASK                0x01ff0000      /* 8 Mentor, DRVVBUS */
+#define DAVINCI_USB_TXINT_MASK \
+       (DAVINCI_USB_TX_ENDPTS_MASK << DAVINCI_USB_TXINT_SHIFT)
+#define DAVINCI_USB_RXINT_MASK \
+       (DAVINCI_USB_RX_ENDPTS_MASK << DAVINCI_USB_RXINT_SHIFT)
+
+#define DAVINCI_BASE_OFFSET            0x400
+
+#endif /* __MUSB_HDRDF_H__ */
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
new file mode 100644 (file)
index 0000000..d68ec6d
--- /dev/null
@@ -0,0 +1,2261 @@
+/*
+ * MUSB OTG driver core code
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Inventra (Multipoint) Dual-Role Controller Driver for Linux.
+ *
+ * This consists of a Host Controller Driver (HCD) and a peripheral
+ * controller driver implementing the "Gadget" API; OTG support is
+ * in the works.  These are normal Linux-USB controller drivers which
+ * use IRQs and have no dedicated thread.
+ *
+ * This version of the driver has only been used with products from
+ * Texas Instruments.  Those products integrate the Inventra logic
+ * with other DMA, IRQ, and bus modules, as well as other logic that
+ * needs to be reflected in this driver.
+ *
+ *
+ * NOTE:  the original Mentor code here was pretty much a collection
+ * of mechanisms that don't seem to have been fully integrated/working
+ * for *any* Linux kernel version.  This version aims at Linux 2.6.now,
+ * Key open issues include:
+ *
+ *  - Lack of host-side transaction scheduling, for all transfer types.
+ *    The hardware doesn't do it; instead, software must.
+ *
+ *    This is not an issue for OTG devices that don't support external
+ *    hubs, but for more "normal" USB hosts it's a user issue that the
+ *    "multipoint" support doesn't scale in the expected ways.  That
+ *    includes DaVinci EVM in a common non-OTG mode.
+ *
+ *      * Control and bulk use dedicated endpoints, and there's as
+ *        yet no mechanism to either (a) reclaim the hardware when
+ *        peripherals are NAKing, which gets complicated with bulk
+ *        endpoints, or (b) use more than a single bulk endpoint in
+ *        each direction.
+ *
+ *        RESULT:  one device may be perceived as blocking another one.
+ *
+ *      * Interrupt and isochronous will dynamically allocate endpoint
+ *        hardware, but (a) there's no record keeping for bandwidth;
+ *        (b) in the common case that few endpoints are available, there
+ *        is no mechanism to reuse endpoints to talk to multiple devices.
+ *
+ *        RESULT:  At one extreme, bandwidth can be overcommitted in
+ *        some hardware configurations, no faults will be reported.
+ *        At the other extreme, the bandwidth capabilities which do
+ *        exist tend to be severely undercommitted.  You can't yet hook
+ *        up both a keyboard and a mouse to an external USB hub.
+ */
+
+/*
+ * This gets many kinds of configuration information:
+ *     - Kconfig for everything user-configurable
+ *     - <asm/arch/hdrc_cnf.h> for SOC or family details
+ *     - platform_device for addressing, irq, and platform_data
+ *     - platform_data is mostly for board-specific informarion
+ *
+ * Most of the conditional compilation will (someday) vanish.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#ifdef CONFIG_ARM
+#include <asm/arch/hardware.h>
+#include <asm/arch/memory.h>
+#include <asm/mach-types.h>
+#endif
+
+#include "musb_core.h"
+
+
+#ifdef CONFIG_ARCH_DAVINCI
+#include "davinci.h"
+#endif
+
+
+
+#if MUSB_DEBUG > 0
+unsigned debug = MUSB_DEBUG;
+module_param(debug, uint, 0);
+MODULE_PARM_DESC(debug, "initial debug message level");
+
+#define MUSB_VERSION_SUFFIX    "/dbg"
+#endif
+
+#define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
+#define DRIVER_DESC "Inventra Dual-Role USB Controller Driver"
+
+#define MUSB_VERSION_BASE "6.0"
+
+#ifndef MUSB_VERSION_SUFFIX
+#define MUSB_VERSION_SUFFIX    ""
+#endif
+#define MUSB_VERSION   MUSB_VERSION_BASE MUSB_VERSION_SUFFIX
+
+#define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION
+
+#define MUSB_DRIVER_NAME "musb_hdrc"
+const char musb_driver_name[] = MUSB_DRIVER_NAME;
+
+MODULE_DESCRIPTION(DRIVER_INFO);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" MUSB_DRIVER_NAME);
+
+
+/*-------------------------------------------------------------------------*/
+
+static inline struct musb *dev_to_musb(struct device *dev)
+{
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       /* usbcore insists dev->driver_data is a "struct hcd *" */
+       return hcd_to_musb(dev_get_drvdata(dev));
+#else
+       return dev_get_drvdata(dev);
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifndef CONFIG_USB_TUSB6010
+/*
+ * Load an endpoint's FIFO
+ */
+void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
+{
+       void __iomem *fifo = hw_ep->fifo;
+
+       prefetch((u8 *)src);
+
+       DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
+                       'T', hw_ep->epnum, fifo, len, src);
+
+       /* we can't assume unaligned reads work */
+       if (likely((0x01 & (unsigned long) src) == 0)) {
+               u16     index = 0;
+
+               /* best case is 32bit-aligned source address */
+               if ((0x02 & (unsigned long) src) == 0) {
+                       if (len >= 4) {
+                               writesl(fifo, src + index, len >> 2);
+                               index += len & ~0x03;
+                       }
+                       if (len & 0x02) {
+                               musb_writew(fifo, 0, *(u16 *)&src[index]);
+                               index += 2;
+                       }
+               } else {
+                       if (len >= 2) {
+                               writesw(fifo, src + index, len >> 1);
+                               index += len & ~0x01;
+                       }
+               }
+               if (len & 0x01)
+                       musb_writeb(fifo, 0, src[index]);
+       } else  {
+               /* byte aligned */
+               writesb(fifo, src, len);
+       }
+}
+
+/*
+ * Unload an endpoint's FIFO
+ */
+void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
+{
+       void __iomem *fifo = hw_ep->fifo;
+
+       DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
+                       'R', hw_ep->epnum, fifo, len, dst);
+
+       /* we can't assume unaligned writes work */
+       if (likely((0x01 & (unsigned long) dst) == 0)) {
+               u16     index = 0;
+
+               /* best case is 32bit-aligned destination address */
+               if ((0x02 & (unsigned long) dst) == 0) {
+                       if (len >= 4) {
+                               readsl(fifo, dst, len >> 2);
+                               index = len & ~0x03;
+                       }
+                       if (len & 0x02) {
+                               *(u16 *)&dst[index] = musb_readw(fifo, 0);
+                               index += 2;
+                       }
+               } else {
+                       if (len >= 2) {
+                               readsw(fifo, dst, len >> 1);
+                               index = len & ~0x01;
+                       }
+               }
+               if (len & 0x01)
+                       dst[index] = musb_readb(fifo, 0);
+       } else  {
+               /* byte aligned */
+               readsb(fifo, dst, len);
+       }
+}
+
+#endif /* normal PIO */
+
+
+/*-------------------------------------------------------------------------*/
+
+/* for high speed test mode; see USB 2.0 spec 7.1.20 */
+static const u8 musb_test_packet[53] = {
+       /* implicit SYNC then DATA0 to start */
+
+       /* JKJKJKJK x9 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       /* JJKKJJKK x8 */
+       0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+       /* JJJJKKKK x8 */
+       0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+       /* JJJJJJJKKKKKKK x8 */
+       0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       /* JJJJJJJK x8 */
+       0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd,
+       /* JKKKKKKK x10, JK */
+       0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e
+
+       /* implicit CRC16 then EOP to end */
+};
+
+void musb_load_testpacket(struct musb *musb)
+{
+       void __iomem    *regs = musb->endpoints[0].regs;
+
+       musb_ep_select(musb->mregs, 0);
+       musb_write_fifo(musb->control_ep,
+                       sizeof(musb_test_packet), musb_test_packet);
+       musb_writew(regs, MUSB_CSR0, MUSB_CSR0_TXPKTRDY);
+}
+
+/*-------------------------------------------------------------------------*/
+
+const char *otg_state_string(struct musb *musb)
+{
+       switch (musb->xceiv.state) {
+       case OTG_STATE_A_IDLE:          return "a_idle";
+       case OTG_STATE_A_WAIT_VRISE:    return "a_wait_vrise";
+       case OTG_STATE_A_WAIT_BCON:     return "a_wait_bcon";
+       case OTG_STATE_A_HOST:          return "a_host";
+       case OTG_STATE_A_SUSPEND:       return "a_suspend";
+       case OTG_STATE_A_PERIPHERAL:    return "a_peripheral";
+       case OTG_STATE_A_WAIT_VFALL:    return "a_wait_vfall";
+       case OTG_STATE_A_VBUS_ERR:      return "a_vbus_err";
+       case OTG_STATE_B_IDLE:          return "b_idle";
+       case OTG_STATE_B_SRP_INIT:      return "b_srp_init";
+       case OTG_STATE_B_PERIPHERAL:    return "b_peripheral";
+       case OTG_STATE_B_WAIT_ACON:     return "b_wait_acon";
+       case OTG_STATE_B_HOST:          return "b_host";
+       default:                        return "UNDEFINED";
+       }
+}
+
+#ifdef CONFIG_USB_MUSB_OTG
+
+/*
+ * See also USB_OTG_1-3.pdf 6.6.5 Timers
+ * REVISIT: Are the other timers done in the hardware?
+ */
+#define TB_ASE0_BRST           100     /* Min 3.125 ms */
+
+/*
+ * Handles OTG hnp timeouts, such as b_ase0_brst
+ */
+void musb_otg_timer_func(unsigned long data)
+{
+       struct musb     *musb = (struct musb *)data;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&musb->lock, flags);
+       switch (musb->xceiv.state) {
+       case OTG_STATE_B_WAIT_ACON:
+               DBG(1, "HNP: b_wait_acon timeout; back to b_peripheral\n");
+               musb_g_disconnect(musb);
+               musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+               musb->is_active = 0;
+               break;
+       case OTG_STATE_A_WAIT_BCON:
+               DBG(1, "HNP: a_wait_bcon timeout; back to a_host\n");
+               musb_hnp_stop(musb);
+               break;
+       default:
+               DBG(1, "HNP: Unhandled mode %s\n", otg_state_string(musb));
+       }
+       musb->ignore_disconnect = 0;
+       spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static DEFINE_TIMER(musb_otg_timer, musb_otg_timer_func, 0, 0);
+
+/*
+ * Stops the B-device HNP state. Caller must take care of locking.
+ */
+void musb_hnp_stop(struct musb *musb)
+{
+       struct usb_hcd  *hcd = musb_to_hcd(musb);
+       void __iomem    *mbase = musb->mregs;
+       u8      reg;
+
+       switch (musb->xceiv.state) {
+       case OTG_STATE_A_PERIPHERAL:
+       case OTG_STATE_A_WAIT_VFALL:
+       case OTG_STATE_A_WAIT_BCON:
+               DBG(1, "HNP: Switching back to A-host\n");
+               musb_g_disconnect(musb);
+               musb->xceiv.state = OTG_STATE_A_IDLE;
+               MUSB_HST_MODE(musb);
+               musb->is_active = 0;
+               break;
+       case OTG_STATE_B_HOST:
+               DBG(1, "HNP: Disabling HR\n");
+               hcd->self.is_b_host = 0;
+               musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+               MUSB_DEV_MODE(musb);
+               reg = musb_readb(mbase, MUSB_POWER);
+               reg |= MUSB_POWER_SUSPENDM;
+               musb_writeb(mbase, MUSB_POWER, reg);
+               /* REVISIT: Start SESSION_REQUEST here? */
+               break;
+       default:
+               DBG(1, "HNP: Stopping in unknown state %s\n",
+                       otg_state_string(musb));
+       }
+
+       /*
+        * When returning to A state after HNP, avoid hub_port_rebounce(),
+        * which cause occasional OPT A "Did not receive reset after connect"
+        * errors.
+        */
+       musb->port1_status &=
+               ~(1 << USB_PORT_FEAT_C_CONNECTION);
+}
+
+#endif
+
+/*
+ * Interrupt Service Routine to record USB "global" interrupts.
+ * Since these do not happen often and signify things of
+ * paramount importance, it seems OK to check them individually;
+ * the order of the tests is specified in the manual
+ *
+ * @param musb instance pointer
+ * @param int_usb register contents
+ * @param devctl
+ * @param power
+ */
+
+#define STAGE0_MASK (MUSB_INTR_RESUME | MUSB_INTR_SESSREQ \
+               | MUSB_INTR_VBUSERROR | MUSB_INTR_CONNECT \
+               | MUSB_INTR_RESET)
+
+static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+                               u8 devctl, u8 power)
+{
+       irqreturn_t handled = IRQ_NONE;
+       void __iomem *mbase = musb->mregs;
+
+       DBG(3, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl,
+               int_usb);
+
+       /* in host mode, the peripheral may issue remote wakeup.
+        * in peripheral mode, the host may resume the link.
+        * spurious RESUME irqs happen too, paired with SUSPEND.
+        */
+       if (int_usb & MUSB_INTR_RESUME) {
+               handled = IRQ_HANDLED;
+               DBG(3, "RESUME (%s)\n", otg_state_string(musb));
+
+               if (devctl & MUSB_DEVCTL_HM) {
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+                       switch (musb->xceiv.state) {
+                       case OTG_STATE_A_SUSPEND:
+                               /* remote wakeup?  later, GetPortStatus
+                                * will stop RESUME signaling
+                                */
+
+                               if (power & MUSB_POWER_SUSPENDM) {
+                                       /* spurious */
+                                       musb->int_usb &= ~MUSB_INTR_SUSPEND;
+                                       DBG(2, "Spurious SUSPENDM\n");
+                                       break;
+                               }
+
+                               power &= ~MUSB_POWER_SUSPENDM;
+                               musb_writeb(mbase, MUSB_POWER,
+                                               power | MUSB_POWER_RESUME);
+
+                               musb->port1_status |=
+                                               (USB_PORT_STAT_C_SUSPEND << 16)
+                                               | MUSB_PORT_STAT_RESUME;
+                               musb->rh_timer = jiffies
+                                               + msecs_to_jiffies(20);
+
+                               musb->xceiv.state = OTG_STATE_A_HOST;
+                               musb->is_active = 1;
+                               usb_hcd_resume_root_hub(musb_to_hcd(musb));
+                               break;
+                       case OTG_STATE_B_WAIT_ACON:
+                               musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+                               musb->is_active = 1;
+                               MUSB_DEV_MODE(musb);
+                               break;
+                       default:
+                               WARNING("bogus %s RESUME (%s)\n",
+                                       "host",
+                                       otg_state_string(musb));
+                       }
+#endif
+               } else {
+                       switch (musb->xceiv.state) {
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+                       case OTG_STATE_A_SUSPEND:
+                               /* possibly DISCONNECT is upcoming */
+                               musb->xceiv.state = OTG_STATE_A_HOST;
+                               usb_hcd_resume_root_hub(musb_to_hcd(musb));
+                               break;
+#endif
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+                       case OTG_STATE_B_WAIT_ACON:
+                       case OTG_STATE_B_PERIPHERAL:
+                               /* disconnect while suspended?  we may
+                                * not get a disconnect irq...
+                                */
+                               if ((devctl & MUSB_DEVCTL_VBUS)
+                                               != (3 << MUSB_DEVCTL_VBUS_SHIFT)
+                                               ) {
+                                       musb->int_usb |= MUSB_INTR_DISCONNECT;
+                                       musb->int_usb &= ~MUSB_INTR_SUSPEND;
+                                       break;
+                               }
+                               musb_g_resume(musb);
+                               break;
+                       case OTG_STATE_B_IDLE:
+                               musb->int_usb &= ~MUSB_INTR_SUSPEND;
+                               break;
+#endif
+                       default:
+                               WARNING("bogus %s RESUME (%s)\n",
+                                       "peripheral",
+                                       otg_state_string(musb));
+                       }
+               }
+       }
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       /* see manual for the order of the tests */
+       if (int_usb & MUSB_INTR_SESSREQ) {
+               DBG(1, "SESSION_REQUEST (%s)\n", otg_state_string(musb));
+
+               /* IRQ arrives from ID pin sense or (later, if VBUS power
+                * is removed) SRP.  responses are time critical:
+                *  - turn on VBUS (with silicon-specific mechanism)
+                *  - go through A_WAIT_VRISE
+                *  - ... to A_WAIT_BCON.
+                * a_wait_vrise_tmout triggers VBUS_ERROR transitions
+                */
+               musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
+               musb->ep0_stage = MUSB_EP0_START;
+               musb->xceiv.state = OTG_STATE_A_IDLE;
+               MUSB_HST_MODE(musb);
+               musb_set_vbus(musb, 1);
+
+               handled = IRQ_HANDLED;
+       }
+
+       if (int_usb & MUSB_INTR_VBUSERROR) {
+               int     ignore = 0;
+
+               /* During connection as an A-Device, we may see a short
+                * current spikes causing voltage drop, because of cable
+                * and peripheral capacitance combined with vbus draw.
+                * (So: less common with truly self-powered devices, where
+                * vbus doesn't act like a power supply.)
+                *
+                * Such spikes are short; usually less than ~500 usec, max
+                * of ~2 msec.  That is, they're not sustained overcurrent
+                * errors, though they're reported using VBUSERROR irqs.
+                *
+                * Workarounds:  (a) hardware: use self powered devices.
+                * (b) software:  ignore non-repeated VBUS errors.
+                *
+                * REVISIT:  do delays from lots of DEBUG_KERNEL checks
+                * make trouble here, keeping VBUS < 4.4V ?
+                */
+               switch (musb->xceiv.state) {
+               case OTG_STATE_A_HOST:
+                       /* recovery is dicey once we've gotten past the
+                        * initial stages of enumeration, but if VBUS
+                        * stayed ok at the other end of the link, and
+                        * another reset is due (at least for high speed,
+                        * to redo the chirp etc), it might work OK...
+                        */
+               case OTG_STATE_A_WAIT_BCON:
+               case OTG_STATE_A_WAIT_VRISE:
+                       if (musb->vbuserr_retry) {
+                               musb->vbuserr_retry--;
+                               ignore = 1;
+                               devctl |= MUSB_DEVCTL_SESSION;
+                               musb_writeb(mbase, MUSB_DEVCTL, devctl);
+                       } else {
+                               musb->port1_status |=
+                                         (1 << USB_PORT_FEAT_OVER_CURRENT)
+                                       | (1 << USB_PORT_FEAT_C_OVER_CURRENT);
+                       }
+                       break;
+               default:
+                       break;
+               }
+
+               DBG(1, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
+                               otg_state_string(musb),
+                               devctl,
+                               ({ char *s;
+                               switch (devctl & MUSB_DEVCTL_VBUS) {
+                               case 0 << MUSB_DEVCTL_VBUS_SHIFT:
+                                       s = "<SessEnd"; break;
+                               case 1 << MUSB_DEVCTL_VBUS_SHIFT:
+                                       s = "<AValid"; break;
+                               case 2 << MUSB_DEVCTL_VBUS_SHIFT:
+                                       s = "<VBusValid"; break;
+                               /* case 3 << MUSB_DEVCTL_VBUS_SHIFT: */
+                               default:
+                                       s = "VALID"; break;
+                               }; s; }),
+                               VBUSERR_RETRY_COUNT - musb->vbuserr_retry,
+                               musb->port1_status);
+
+               /* go through A_WAIT_VFALL then start a new session */
+               if (!ignore)
+                       musb_set_vbus(musb, 0);
+               handled = IRQ_HANDLED;
+       }
+
+       if (int_usb & MUSB_INTR_CONNECT) {
+               struct usb_hcd *hcd = musb_to_hcd(musb);
+
+               handled = IRQ_HANDLED;
+               musb->is_active = 1;
+               set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+
+               musb->ep0_stage = MUSB_EP0_START;
+
+#ifdef CONFIG_USB_MUSB_OTG
+               /* flush endpoints when transitioning from Device Mode */
+               if (is_peripheral_active(musb)) {
+                       /* REVISIT HNP; just force disconnect */
+               }
+               musb_writew(mbase, MUSB_INTRTXE, musb->epmask);
+               musb_writew(mbase, MUSB_INTRRXE, musb->epmask & 0xfffe);
+               musb_writeb(mbase, MUSB_INTRUSBE, 0xf7);
+#endif
+               musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED
+                                       |USB_PORT_STAT_HIGH_SPEED
+                                       |USB_PORT_STAT_ENABLE
+                                       );
+               musb->port1_status |= USB_PORT_STAT_CONNECTION
+                                       |(USB_PORT_STAT_C_CONNECTION << 16);
+
+               /* high vs full speed is just a guess until after reset */
+               if (devctl & MUSB_DEVCTL_LSDEV)
+                       musb->port1_status |= USB_PORT_STAT_LOW_SPEED;
+
+               if (hcd->status_urb)
+                       usb_hcd_poll_rh_status(hcd);
+               else
+                       usb_hcd_resume_root_hub(hcd);
+
+               MUSB_HST_MODE(musb);
+
+               /* indicate new connection to OTG machine */
+               switch (musb->xceiv.state) {
+               case OTG_STATE_B_PERIPHERAL:
+                       if (int_usb & MUSB_INTR_SUSPEND) {
+                               DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n");
+                               musb->xceiv.state = OTG_STATE_B_HOST;
+                               hcd->self.is_b_host = 1;
+                               int_usb &= ~MUSB_INTR_SUSPEND;
+                       } else
+                               DBG(1, "CONNECT as b_peripheral???\n");
+                       break;
+               case OTG_STATE_B_WAIT_ACON:
+                       DBG(1, "HNP: Waiting to switch to b_host state\n");
+                       musb->xceiv.state = OTG_STATE_B_HOST;
+                       hcd->self.is_b_host = 1;
+                       break;
+               default:
+                       if ((devctl & MUSB_DEVCTL_VBUS)
+                                       == (3 << MUSB_DEVCTL_VBUS_SHIFT)) {
+                               musb->xceiv.state = OTG_STATE_A_HOST;
+                               hcd->self.is_b_host = 0;
+                       }
+                       break;
+               }
+               DBG(1, "CONNECT (%s) devctl %02x\n",
+                               otg_state_string(musb), devctl);
+       }
+#endif /* CONFIG_USB_MUSB_HDRC_HCD */
+
+       /* mentor saves a bit: bus reset and babble share the same irq.
+        * only host sees babble; only peripheral sees bus reset.
+        */
+       if (int_usb & MUSB_INTR_RESET) {
+               if (is_host_capable() && (devctl & MUSB_DEVCTL_HM) != 0) {
+                       /*
+                        * Looks like non-HS BABBLE can be ignored, but
+                        * HS BABBLE is an error condition. For HS the solution
+                        * is to avoid babble in the first place and fix what
+                        * caused BABBLE. When HS BABBLE happens we can only
+                        * stop the session.
+                        */
+                       if (devctl & (MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV))
+                               DBG(1, "BABBLE devctl: %02x\n", devctl);
+                       else {
+                               ERR("Stopping host session -- babble\n");
+                               musb_writeb(mbase, MUSB_DEVCTL, 0);
+                       }
+               } else if (is_peripheral_capable()) {
+                       DBG(1, "BUS RESET as %s\n", otg_state_string(musb));
+                       switch (musb->xceiv.state) {
+#ifdef CONFIG_USB_OTG
+                       case OTG_STATE_A_SUSPEND:
+                               /* We need to ignore disconnect on suspend
+                                * otherwise tusb 2.0 won't reconnect after a
+                                * power cycle, which breaks otg compliance.
+                                */
+                               musb->ignore_disconnect = 1;
+                               musb_g_reset(musb);
+                               /* FALLTHROUGH */
+                       case OTG_STATE_A_WAIT_BCON:     /* OPT TD.4.7-900ms */
+                               DBG(1, "HNP: Setting timer as %s\n",
+                                               otg_state_string(musb));
+                               musb_otg_timer.data = (unsigned long)musb;
+                               mod_timer(&musb_otg_timer, jiffies
+                                       + msecs_to_jiffies(100));
+                               break;
+                       case OTG_STATE_A_PERIPHERAL:
+                               musb_hnp_stop(musb);
+                               break;
+                       case OTG_STATE_B_WAIT_ACON:
+                               DBG(1, "HNP: RESET (%s), to b_peripheral\n",
+                                       otg_state_string(musb));
+                               musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+                               musb_g_reset(musb);
+                               break;
+#endif
+                       case OTG_STATE_B_IDLE:
+                               musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+                               /* FALLTHROUGH */
+                       case OTG_STATE_B_PERIPHERAL:
+                               musb_g_reset(musb);
+                               break;
+                       default:
+                               DBG(1, "Unhandled BUS RESET as %s\n",
+                                       otg_state_string(musb));
+                       }
+               }
+
+               handled = IRQ_HANDLED;
+       }
+       schedule_work(&musb->irq_work);
+
+       return handled;
+}
+
+/*
+ * Interrupt Service Routine to record USB "global" interrupts.
+ * Since these do not happen often and signify things of
+ * paramount importance, it seems OK to check them individually;
+ * the order of the tests is specified in the manual
+ *
+ * @param musb instance pointer
+ * @param int_usb register contents
+ * @param devctl
+ * @param power
+ */
+static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
+                               u8 devctl, u8 power)
+{
+       irqreturn_t handled = IRQ_NONE;
+
+#if 0
+/* REVISIT ... this would be for multiplexing periodic endpoints, or
+ * supporting transfer phasing to prevent exceeding ISO bandwidth
+ * limits of a given frame or microframe.
+ *
+ * It's not needed for peripheral side, which dedicates endpoints;
+ * though it _might_ use SOF irqs for other purposes.
+ *
+ * And it's not currently needed for host side, which also dedicates
+ * endpoints, relies on TX/RX interval registers, and isn't claimed
+ * to support ISO transfers yet.
+ */
+       if (int_usb & MUSB_INTR_SOF) {
+               void __iomem *mbase = musb->mregs;
+               struct musb_hw_ep       *ep;
+               u8 epnum;
+               u16 frame;
+
+               DBG(6, "START_OF_FRAME\n");
+               handled = IRQ_HANDLED;
+
+               /* start any periodic Tx transfers waiting for current frame */
+               frame = musb_readw(mbase, MUSB_FRAME);
+               ep = musb->endpoints;
+               for (epnum = 1; (epnum < musb->nr_endpoints)
+                                       && (musb->epmask >= (1 << epnum));
+                               epnum++, ep++) {
+                       /*
+                        * FIXME handle framecounter wraps (12 bits)
+                        * eliminate duplicated StartUrb logic
+                        */
+                       if (ep->dwWaitFrame >= frame) {
+                               ep->dwWaitFrame = 0;
+                               pr_debug("SOF --> periodic TX%s on %d\n",
+                                       ep->tx_channel ? " DMA" : "",
+                                       epnum);
+                               if (!ep->tx_channel)
+                                       musb_h_tx_start(musb, epnum);
+                               else
+                                       cppi_hostdma_start(musb, epnum);
+                       }
+               }               /* end of for loop */
+       }
+#endif
+
+       if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
+               DBG(1, "DISCONNECT (%s) as %s, devctl %02x\n",
+                               otg_state_string(musb),
+                               MUSB_MODE(musb), devctl);
+               handled = IRQ_HANDLED;
+
+               switch (musb->xceiv.state) {
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+               case OTG_STATE_A_HOST:
+               case OTG_STATE_A_SUSPEND:
+                       musb_root_disconnect(musb);
+                       if (musb->a_wait_bcon != 0)
+                               musb_platform_try_idle(musb, jiffies
+                                       + msecs_to_jiffies(musb->a_wait_bcon));
+                       break;
+#endif /* HOST */
+#ifdef CONFIG_USB_MUSB_OTG
+               case OTG_STATE_B_HOST:
+                       musb_hnp_stop(musb);
+                       break;
+               case OTG_STATE_A_PERIPHERAL:
+                       musb_hnp_stop(musb);
+                       musb_root_disconnect(musb);
+                       /* FALLTHROUGH */
+               case OTG_STATE_B_WAIT_ACON:
+                       /* FALLTHROUGH */
+#endif /* OTG */
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+               case OTG_STATE_B_PERIPHERAL:
+               case OTG_STATE_B_IDLE:
+                       musb_g_disconnect(musb);
+                       break;
+#endif /* GADGET */
+               default:
+                       WARNING("unhandled DISCONNECT transition (%s)\n",
+                               otg_state_string(musb));
+                       break;
+               }
+
+               schedule_work(&musb->irq_work);
+       }
+
+       if (int_usb & MUSB_INTR_SUSPEND) {
+               DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",
+                               otg_state_string(musb), devctl, power);
+               handled = IRQ_HANDLED;
+
+               switch (musb->xceiv.state) {
+#ifdef CONFIG_USB_MUSB_OTG
+               case OTG_STATE_A_PERIPHERAL:
+                       /*
+                        * We cannot stop HNP here, devctl BDEVICE might be
+                        * still set.
+                        */
+                       break;
+#endif
+               case OTG_STATE_B_PERIPHERAL:
+                       musb_g_suspend(musb);
+                       musb->is_active = is_otg_enabled(musb)
+                                       && musb->xceiv.gadget->b_hnp_enable;
+                       if (musb->is_active) {
+#ifdef CONFIG_USB_MUSB_OTG
+                               musb->xceiv.state = OTG_STATE_B_WAIT_ACON;
+                               DBG(1, "HNP: Setting timer for b_ase0_brst\n");
+                               musb_otg_timer.data = (unsigned long)musb;
+                               mod_timer(&musb_otg_timer, jiffies
+                                       + msecs_to_jiffies(TB_ASE0_BRST));
+#endif
+                       }
+                       break;
+               case OTG_STATE_A_WAIT_BCON:
+                       if (musb->a_wait_bcon != 0)
+                               musb_platform_try_idle(musb, jiffies
+                                       + msecs_to_jiffies(musb->a_wait_bcon));
+                       break;
+               case OTG_STATE_A_HOST:
+                       musb->xceiv.state = OTG_STATE_A_SUSPEND;
+                       musb->is_active = is_otg_enabled(musb)
+                                       && musb->xceiv.host->b_hnp_enable;
+                       break;
+               case OTG_STATE_B_HOST:
+                       /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
+                       DBG(1, "REVISIT: SUSPEND as B_HOST\n");
+                       break;
+               default:
+                       /* "should not happen" */
+                       musb->is_active = 0;
+                       break;
+               }
+               schedule_work(&musb->irq_work);
+       }
+
+
+       return handled;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+* Program the HDRC to start (enable interrupts, dma, etc.).
+*/
+void musb_start(struct musb *musb)
+{
+       void __iomem    *regs = musb->mregs;
+       u8              devctl = musb_readb(regs, MUSB_DEVCTL);
+
+       DBG(2, "<== devctl %02x\n", devctl);
+
+       /*  Set INT enable registers, enable interrupts */
+       musb_writew(regs, MUSB_INTRTXE, musb->epmask);
+       musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe);
+       musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
+
+       musb_writeb(regs, MUSB_TESTMODE, 0);
+
+       /* put into basic highspeed mode and start session */
+       musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
+                                               | MUSB_POWER_SOFTCONN
+                                               | MUSB_POWER_HSENAB
+                                               /* ENSUSPEND wedges tusb */
+                                               /* | MUSB_POWER_ENSUSPEND */
+                                               );
+
+       musb->is_active = 0;
+       devctl = musb_readb(regs, MUSB_DEVCTL);
+       devctl &= ~MUSB_DEVCTL_SESSION;
+
+       if (is_otg_enabled(musb)) {
+               /* session started after:
+                * (a) ID-grounded irq, host mode;
+                * (b) vbus present/connect IRQ, peripheral mode;
+                * (c) peripheral initiates, using SRP
+                */
+               if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+                       musb->is_active = 1;
+               else
+                       devctl |= MUSB_DEVCTL_SESSION;
+
+       } else if (is_host_enabled(musb)) {
+               /* assume ID pin is hard-wired to ground */
+               devctl |= MUSB_DEVCTL_SESSION;
+
+       } else /* peripheral is enabled */ {
+               if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+                       musb->is_active = 1;
+       }
+       musb_platform_enable(musb);
+       musb_writeb(regs, MUSB_DEVCTL, devctl);
+}
+
+
+static void musb_generic_disable(struct musb *musb)
+{
+       void __iomem    *mbase = musb->mregs;
+       u16     temp;
+
+       /* disable interrupts */
+       musb_writeb(mbase, MUSB_INTRUSBE, 0);
+       musb_writew(mbase, MUSB_INTRTXE, 0);
+       musb_writew(mbase, MUSB_INTRRXE, 0);
+
+       /* off */
+       musb_writeb(mbase, MUSB_DEVCTL, 0);
+
+       /*  flush pending interrupts */
+       temp = musb_readb(mbase, MUSB_INTRUSB);
+       temp = musb_readw(mbase, MUSB_INTRTX);
+       temp = musb_readw(mbase, MUSB_INTRRX);
+
+}
+
+/*
+ * Make the HDRC stop (disable interrupts, etc.);
+ * reversible by musb_start
+ * called on gadget driver unregister
+ * with controller locked, irqs blocked
+ * acts as a NOP unless some role activated the hardware
+ */
+void musb_stop(struct musb *musb)
+{
+       /* stop IRQs, timers, ... */
+       musb_platform_disable(musb);
+       musb_generic_disable(musb);
+       DBG(3, "HDRC disabled\n");
+
+       /* FIXME
+        *  - mark host and/or peripheral drivers unusable/inactive
+        *  - disable DMA (and enable it in HdrcStart)
+        *  - make sure we can musb_start() after musb_stop(); with
+        *    OTG mode, gadget driver module rmmod/modprobe cycles that
+        *  - ...
+        */
+       musb_platform_try_idle(musb, 0);
+}
+
+static void musb_shutdown(struct platform_device *pdev)
+{
+       struct musb     *musb = dev_to_musb(&pdev->dev);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&musb->lock, flags);
+       musb_platform_disable(musb);
+       musb_generic_disable(musb);
+       if (musb->clock) {
+               clk_put(musb->clock);
+               musb->clock = NULL;
+       }
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       /* FIXME power down */
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * The silicon either has hard-wired endpoint configurations, or else
+ * "dynamic fifo" sizing.  The driver has support for both, though at this
+ * writing only the dynamic sizing is very well tested.   We use normal
+ * idioms to so both modes are compile-tested, but dead code elimination
+ * leaves only the relevant one in the object file.
+ *
+ * We don't currently use dynamic fifo setup capability to do anything
+ * more than selecting one of a bunch of predefined configurations.
+ */
+#if defined(CONFIG_USB_TUSB6010) || \
+       defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+static ushort __initdata fifo_mode = 4;
+#else
+static ushort __initdata fifo_mode = 2;
+#endif
+
+/* "modprobe ... fifo_mode=1" etc */
+module_param(fifo_mode, ushort, 0);
+MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration");
+
+
+enum fifo_style { FIFO_RXTX, FIFO_TX, FIFO_RX } __attribute__ ((packed));
+enum buf_mode { BUF_SINGLE, BUF_DOUBLE } __attribute__ ((packed));
+
+struct fifo_cfg {
+       u8              hw_ep_num;
+       enum fifo_style style;
+       enum buf_mode   mode;
+       u16             maxpacket;
+};
+
+/*
+ * tables defining fifo_mode values.  define more if you like.
+ * for host side, make sure both halves of ep1 are set up.
+ */
+
+/* mode 0 - fits in 2KB */
+static struct fifo_cfg __initdata mode_0_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 1 - fits in 4KB */
+static struct fifo_cfg __initdata mode_1_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 2 - fits in 4KB */
+static struct fifo_cfg __initdata mode_2_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 3 - fits in 4KB */
+static struct fifo_cfg __initdata mode_3_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 4 - fits in 16KB */
+static struct fifo_cfg __initdata mode_4_cfg[] = {
+{ .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  2, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  3, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  3, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  4, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  4, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  5, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  5, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  6, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  6, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  7, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  7, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  8, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  8, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  9, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  9, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num = 10, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num = 10, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num = 11, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num = 11, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num = 12, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num = 12, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num = 13, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num = 13, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, },
+{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, },
+};
+
+
+/*
+ * configure a fifo; for non-shared endpoints, this may be called
+ * once for a tx fifo and once for an rx fifo.
+ *
+ * returns negative errno or offset for next fifo.
+ */
+static int __init
+fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
+               const struct fifo_cfg *cfg, u16 offset)
+{
+       void __iomem    *mbase = musb->mregs;
+       int     size = 0;
+       u16     maxpacket = cfg->maxpacket;
+       u16     c_off = offset >> 3;
+       u8      c_size;
+
+       /* expect hw_ep has already been zero-initialized */
+
+       size = ffs(max(maxpacket, (u16) 8)) - 1;
+       maxpacket = 1 << size;
+
+       c_size = size - 3;
+       if (cfg->mode == BUF_DOUBLE) {
+               if ((offset + (maxpacket << 1)) >
+                               (1 << (musb->config->ram_bits + 2)))
+                       return -EMSGSIZE;
+               c_size |= MUSB_FIFOSZ_DPB;
+       } else {
+               if ((offset + maxpacket) > (1 << (musb->config->ram_bits + 2)))
+                       return -EMSGSIZE;
+       }
+
+       /* configure the FIFO */
+       musb_writeb(mbase, MUSB_INDEX, hw_ep->epnum);
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       /* EP0 reserved endpoint for control, bidirectional;
+        * EP1 reserved for bulk, two unidirection halves.
+        */
+       if (hw_ep->epnum == 1)
+               musb->bulk_ep = hw_ep;
+       /* REVISIT error check:  be sure ep0 can both rx and tx ... */
+#endif
+       switch (cfg->style) {
+       case FIFO_TX:
+               musb_writeb(mbase, MUSB_TXFIFOSZ, c_size);
+               musb_writew(mbase, MUSB_TXFIFOADD, c_off);
+               hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
+               hw_ep->max_packet_sz_tx = maxpacket;
+               break;
+       case FIFO_RX:
+               musb_writeb(mbase, MUSB_RXFIFOSZ, c_size);
+               musb_writew(mbase, MUSB_RXFIFOADD, c_off);
+               hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
+               hw_ep->max_packet_sz_rx = maxpacket;
+               break;
+       case FIFO_RXTX:
+               musb_writeb(mbase, MUSB_TXFIFOSZ, c_size);
+               musb_writew(mbase, MUSB_TXFIFOADD, c_off);
+               hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
+               hw_ep->max_packet_sz_rx = maxpacket;
+
+               musb_writeb(mbase, MUSB_RXFIFOSZ, c_size);
+               musb_writew(mbase, MUSB_RXFIFOADD, c_off);
+               hw_ep->tx_double_buffered = hw_ep->rx_double_buffered;
+               hw_ep->max_packet_sz_tx = maxpacket;
+
+               hw_ep->is_shared_fifo = true;
+               break;
+       }
+
+       /* NOTE rx and tx endpoint irqs aren't managed separately,
+        * which happens to be ok
+        */
+       musb->epmask |= (1 << hw_ep->epnum);
+
+       return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));
+}
+
+static struct fifo_cfg __initdata ep0_cfg = {
+       .style = FIFO_RXTX, .maxpacket = 64,
+};
+
+static int __init ep_config_from_table(struct musb *musb)
+{
+       const struct fifo_cfg   *cfg;
+       unsigned                i, n;
+       int                     offset;
+       struct musb_hw_ep       *hw_ep = musb->endpoints;
+
+       switch (fifo_mode) {
+       default:
+               fifo_mode = 0;
+               /* FALLTHROUGH */
+       case 0:
+               cfg = mode_0_cfg;
+               n = ARRAY_SIZE(mode_0_cfg);
+               break;
+       case 1:
+               cfg = mode_1_cfg;
+               n = ARRAY_SIZE(mode_1_cfg);
+               break;
+       case 2:
+               cfg = mode_2_cfg;
+               n = ARRAY_SIZE(mode_2_cfg);
+               break;
+       case 3:
+               cfg = mode_3_cfg;
+               n = ARRAY_SIZE(mode_3_cfg);
+               break;
+       case 4:
+               cfg = mode_4_cfg;
+               n = ARRAY_SIZE(mode_4_cfg);
+               break;
+       }
+
+       printk(KERN_DEBUG "%s: setup fifo_mode %d\n",
+                       musb_driver_name, fifo_mode);
+
+
+       offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0);
+       /* assert(offset > 0) */
+
+       /* NOTE:  for RTL versions >= 1.400 EPINFO and RAMINFO would
+        * be better than static musb->config->num_eps and DYN_FIFO_SIZE...
+        */
+
+       for (i = 0; i < n; i++) {
+               u8      epn = cfg->hw_ep_num;
+
+               if (epn >= musb->config->num_eps) {
+                       pr_debug("%s: invalid ep %d\n",
+                                       musb_driver_name, epn);
+                       continue;
+               }
+               offset = fifo_setup(musb, hw_ep + epn, cfg++, offset);
+               if (offset < 0) {
+                       pr_debug("%s: mem overrun, ep %d\n",
+                                       musb_driver_name, epn);
+                       return -EINVAL;
+               }
+               epn++;
+               musb->nr_endpoints = max(epn, musb->nr_endpoints);
+       }
+
+       printk(KERN_DEBUG "%s: %d/%d max ep, %d/%d memory\n",
+                       musb_driver_name,
+                       n + 1, musb->config->num_eps * 2 - 1,
+                       offset, (1 << (musb->config->ram_bits + 2)));
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       if (!musb->bulk_ep) {
+               pr_debug("%s: missing bulk\n", musb_driver_name);
+               return -EINVAL;
+       }
+#endif
+
+       return 0;
+}
+
+
+/*
+ * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
+ * @param musb the controller
+ */
+static int __init ep_config_from_hw(struct musb *musb)
+{
+       u8 epnum = 0, reg;
+       struct musb_hw_ep *hw_ep;
+       void *mbase = musb->mregs;
+
+       DBG(2, "<== static silicon ep config\n");
+
+       /* FIXME pick up ep0 maxpacket size */
+
+       for (epnum = 1; epnum < musb->config->num_eps; epnum++) {
+               musb_ep_select(mbase, epnum);
+               hw_ep = musb->endpoints + epnum;
+
+               /* read from core using indexed model */
+               reg = musb_readb(hw_ep->regs, 0x10 + MUSB_FIFOSIZE);
+               if (!reg) {
+                       /* 0's returned when no more endpoints */
+                       break;
+               }
+               musb->nr_endpoints++;
+               musb->epmask |= (1 << epnum);
+
+               hw_ep->max_packet_sz_tx = 1 << (reg & 0x0f);
+
+               /* shared TX/RX FIFO? */
+               if ((reg & 0xf0) == 0xf0) {
+                       hw_ep->max_packet_sz_rx = hw_ep->max_packet_sz_tx;
+                       hw_ep->is_shared_fifo = true;
+                       continue;
+               } else {
+                       hw_ep->max_packet_sz_rx = 1 << ((reg & 0xf0) >> 4);
+                       hw_ep->is_shared_fifo = false;
+               }
+
+               /* FIXME set up hw_ep->{rx,tx}_double_buffered */
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+               /* pick an RX/TX endpoint for bulk */
+               if (hw_ep->max_packet_sz_tx < 512
+                               || hw_ep->max_packet_sz_rx < 512)
+                       continue;
+
+               /* REVISIT:  this algorithm is lazy, we should at least
+                * try to pick a double buffered endpoint.
+                */
+               if (musb->bulk_ep)
+                       continue;
+               musb->bulk_ep = hw_ep;
+#endif
+       }
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       if (!musb->bulk_ep) {
+               pr_debug("%s: missing bulk\n", musb_driver_name);
+               return -EINVAL;
+       }
+#endif
+
+       return 0;
+}
+
+enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, };
+
+/* Initialize MUSB (M)HDRC part of the USB hardware subsystem;
+ * configure endpoints, or take their config from silicon
+ */
+static int __init musb_core_init(u16 musb_type, struct musb *musb)
+{
+#ifdef MUSB_AHB_ID
+       u32 data;
+#endif
+       u8 reg;
+       char *type;
+       u16 hwvers, rev_major, rev_minor;
+       char aInfo[78], aRevision[32], aDate[12];
+       void __iomem    *mbase = musb->mregs;
+       int             status = 0;
+       int             i;
+
+       /* log core options (read using indexed model) */
+       musb_ep_select(mbase, 0);
+       reg = musb_readb(mbase, 0x10 + MUSB_CONFIGDATA);
+
+       strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8");
+       if (reg & MUSB_CONFIGDATA_DYNFIFO)
+               strcat(aInfo, ", dyn FIFOs");
+       if (reg & MUSB_CONFIGDATA_MPRXE) {
+               strcat(aInfo, ", bulk combine");
+#ifdef C_MP_RX
+               musb->bulk_combine = true;
+#else
+               strcat(aInfo, " (X)");          /* no driver support */
+#endif
+       }
+       if (reg & MUSB_CONFIGDATA_MPTXE) {
+               strcat(aInfo, ", bulk split");
+#ifdef C_MP_TX
+               musb->bulk_split = true;
+#else
+               strcat(aInfo, " (X)");          /* no driver support */
+#endif
+       }
+       if (reg & MUSB_CONFIGDATA_HBRXE) {
+               strcat(aInfo, ", HB-ISO Rx");
+               strcat(aInfo, " (X)");          /* no driver support */
+       }
+       if (reg & MUSB_CONFIGDATA_HBTXE) {
+               strcat(aInfo, ", HB-ISO Tx");
+               strcat(aInfo, " (X)");          /* no driver support */
+       }
+       if (reg & MUSB_CONFIGDATA_SOFTCONE)
+               strcat(aInfo, ", SoftConn");
+
+       printk(KERN_DEBUG "%s: ConfigData=0x%02x (%s)\n",
+                       musb_driver_name, reg, aInfo);
+
+#ifdef MUSB_AHB_ID
+       data = musb_readl(mbase, 0x404);
+       sprintf(aDate, "%04d-%02x-%02x", (data & 0xffff),
+               (data >> 16) & 0xff, (data >> 24) & 0xff);
+       /* FIXME ID2 and ID3 are unused */
+       data = musb_readl(mbase, 0x408);
+       printk(KERN_DEBUG "ID2=%lx\n", (long unsigned)data);
+       data = musb_readl(mbase, 0x40c);
+       printk(KERN_DEBUG "ID3=%lx\n", (long unsigned)data);
+       reg = musb_readb(mbase, 0x400);
+       musb_type = ('M' == reg) ? MUSB_CONTROLLER_MHDRC : MUSB_CONTROLLER_HDRC;
+#else
+       aDate[0] = 0;
+#endif
+       if (MUSB_CONTROLLER_MHDRC == musb_type) {
+               musb->is_multipoint = 1;
+               type = "M";
+       } else {
+               musb->is_multipoint = 0;
+               type = "";
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+#ifndef        CONFIG_USB_OTG_BLACKLIST_HUB
+               printk(KERN_ERR
+                       "%s: kernel must blacklist external hubs\n",
+                       musb_driver_name);
+#endif
+#endif
+       }
+
+       /* log release info */
+       hwvers = musb_readw(mbase, MUSB_HWVERS);
+       rev_major = (hwvers >> 10) & 0x1f;
+       rev_minor = hwvers & 0x3ff;
+       snprintf(aRevision, 32, "%d.%d%s", rev_major,
+               rev_minor, (hwvers & 0x8000) ? "RC" : "");
+       printk(KERN_DEBUG "%s: %sHDRC RTL version %s %s\n",
+                       musb_driver_name, type, aRevision, aDate);
+
+       /* configure ep0 */
+       musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;
+       musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;
+
+       /* discover endpoint configuration */
+       musb->nr_endpoints = 1;
+       musb->epmask = 1;
+
+       if (reg & MUSB_CONFIGDATA_DYNFIFO) {
+               if (musb->config->dyn_fifo)
+                       status = ep_config_from_table(musb);
+               else {
+                       ERR("reconfigure software for Dynamic FIFOs\n");
+                       status = -ENODEV;
+               }
+       } else {
+               if (!musb->config->dyn_fifo)
+                       status = ep_config_from_hw(musb);
+               else {
+                       ERR("reconfigure software for static FIFOs\n");
+                       return -ENODEV;
+               }
+       }
+
+       if (status < 0)
+               return status;
+
+       /* finish init, and print endpoint config */
+       for (i = 0; i < musb->nr_endpoints; i++) {
+               struct musb_hw_ep       *hw_ep = musb->endpoints + i;
+
+               hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase;
+#ifdef CONFIG_USB_TUSB6010
+               hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i);
+               hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i);
+               hw_ep->fifo_sync_va =
+                       musb->sync_va + 0x400 + MUSB_FIFO_OFFSET(i);
+
+               if (i == 0)
+                       hw_ep->conf = mbase - 0x400 + TUSB_EP0_CONF;
+               else
+                       hw_ep->conf = mbase + 0x400 + (((i - 1) & 0xf) << 2);
+#endif
+
+               hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase;
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+               hw_ep->target_regs = MUSB_BUSCTL_OFFSET(i, 0) + mbase;
+               hw_ep->rx_reinit = 1;
+               hw_ep->tx_reinit = 1;
+#endif
+
+               if (hw_ep->max_packet_sz_tx) {
+                       printk(KERN_DEBUG
+                               "%s: hw_ep %d%s, %smax %d\n",
+                               musb_driver_name, i,
+                               hw_ep->is_shared_fifo ? "shared" : "tx",
+                               hw_ep->tx_double_buffered
+                                       ? "doublebuffer, " : "",
+                               hw_ep->max_packet_sz_tx);
+               }
+               if (hw_ep->max_packet_sz_rx && !hw_ep->is_shared_fifo) {
+                       printk(KERN_DEBUG
+                               "%s: hw_ep %d%s, %smax %d\n",
+                               musb_driver_name, i,
+                               "rx",
+                               hw_ep->rx_double_buffered
+                                       ? "doublebuffer, " : "",
+                               hw_ep->max_packet_sz_rx);
+               }
+               if (!(hw_ep->max_packet_sz_tx || hw_ep->max_packet_sz_rx))
+                       DBG(1, "hw_ep %d not configured\n", i);
+       }
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+
+static irqreturn_t generic_interrupt(int irq, void *__hci)
+{
+       unsigned long   flags;
+       irqreturn_t     retval = IRQ_NONE;
+       struct musb     *musb = __hci;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+       musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+       musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+       if (musb->int_usb || musb->int_tx || musb->int_rx)
+               retval = musb_interrupt(musb);
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       /* REVISIT we sometimes get spurious IRQs on g_ep0
+        * not clear why...
+        */
+       if (retval != IRQ_HANDLED)
+               DBG(5, "spurious?\n");
+
+       return IRQ_HANDLED;
+}
+
+#else
+#define generic_interrupt      NULL
+#endif
+
+/*
+ * handle all the irqs defined by the HDRC core. for now we expect:  other
+ * irq sources (phy, dma, etc) will be handled first, musb->int_* values
+ * will be assigned, and the irq will already have been acked.
+ *
+ * called in irq context with spinlock held, irqs blocked
+ */
+irqreturn_t musb_interrupt(struct musb *musb)
+{
+       irqreturn_t     retval = IRQ_NONE;
+       u8              devctl, power;
+       int             ep_num;
+       u32             reg;
+
+       devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+       power = musb_readb(musb->mregs, MUSB_POWER);
+
+       DBG(4, "** IRQ %s usb%04x tx%04x rx%04x\n",
+               (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
+               musb->int_usb, musb->int_tx, musb->int_rx);
+
+       /* the core can interrupt us for multiple reasons; docs have
+        * a generic interrupt flowchart to follow
+        */
+       if (musb->int_usb & STAGE0_MASK)
+               retval |= musb_stage0_irq(musb, musb->int_usb,
+                               devctl, power);
+
+       /* "stage 1" is handling endpoint irqs */
+
+       /* handle endpoint 0 first */
+       if (musb->int_tx & 1) {
+               if (devctl & MUSB_DEVCTL_HM)
+                       retval |= musb_h_ep0_irq(musb);
+               else
+                       retval |= musb_g_ep0_irq(musb);
+       }
+
+       /* RX on endpoints 1-15 */
+       reg = musb->int_rx >> 1;
+       ep_num = 1;
+       while (reg) {
+               if (reg & 1) {
+                       /* musb_ep_select(musb->mregs, ep_num); */
+                       /* REVISIT just retval = ep->rx_irq(...) */
+                       retval = IRQ_HANDLED;
+                       if (devctl & MUSB_DEVCTL_HM) {
+                               if (is_host_capable())
+                                       musb_host_rx(musb, ep_num);
+                       } else {
+                               if (is_peripheral_capable())
+                                       musb_g_rx(musb, ep_num);
+                       }
+               }
+
+               reg >>= 1;
+               ep_num++;
+       }
+
+       /* TX on endpoints 1-15 */
+       reg = musb->int_tx >> 1;
+       ep_num = 1;
+       while (reg) {
+               if (reg & 1) {
+                       /* musb_ep_select(musb->mregs, ep_num); */
+                       /* REVISIT just retval |= ep->tx_irq(...) */
+                       retval = IRQ_HANDLED;
+                       if (devctl & MUSB_DEVCTL_HM) {
+                               if (is_host_capable())
+                                       musb_host_tx(musb, ep_num);
+                       } else {
+                               if (is_peripheral_capable())
+                                       musb_g_tx(musb, ep_num);
+                       }
+               }
+               reg >>= 1;
+               ep_num++;
+       }
+
+       /* finish handling "global" interrupts after handling fifos */
+       if (musb->int_usb)
+               retval |= musb_stage2_irq(musb,
+                               musb->int_usb, devctl, power);
+
+       return retval;
+}
+
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+static int __initdata use_dma = 1;
+
+/* "modprobe ... use_dma=0" etc */
+module_param(use_dma, bool, 0);
+MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
+
+void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
+{
+       u8      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+       /* called with controller lock already held */
+
+       if (!epnum) {
+#ifndef CONFIG_USB_TUSB_OMAP_DMA
+               if (!is_cppi_enabled()) {
+                       /* endpoint 0 */
+                       if (devctl & MUSB_DEVCTL_HM)
+                               musb_h_ep0_irq(musb);
+                       else
+                               musb_g_ep0_irq(musb);
+               }
+#endif
+       } else {
+               /* endpoints 1..15 */
+               if (transmit) {
+                       if (devctl & MUSB_DEVCTL_HM) {
+                               if (is_host_capable())
+                                       musb_host_tx(musb, epnum);
+                       } else {
+                               if (is_peripheral_capable())
+                                       musb_g_tx(musb, epnum);
+                       }
+               } else {
+                       /* receive */
+                       if (devctl & MUSB_DEVCTL_HM) {
+                               if (is_host_capable())
+                                       musb_host_rx(musb, epnum);
+                       } else {
+                               if (is_peripheral_capable())
+                                       musb_g_rx(musb, epnum);
+                       }
+               }
+       }
+}
+
+#else
+#define use_dma                        0
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_SYSFS
+
+static ssize_t
+musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct musb *musb = dev_to_musb(dev);
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       spin_lock_irqsave(&musb->lock, flags);
+       ret = sprintf(buf, "%s\n", otg_state_string(musb));
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       return ret;
+}
+
+static ssize_t
+musb_mode_store(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t n)
+{
+       struct musb     *musb = dev_to_musb(dev);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&musb->lock, flags);
+       if (!strncmp(buf, "host", 4))
+               musb_platform_set_mode(musb, MUSB_HOST);
+       if (!strncmp(buf, "peripheral", 10))
+               musb_platform_set_mode(musb, MUSB_PERIPHERAL);
+       if (!strncmp(buf, "otg", 3))
+               musb_platform_set_mode(musb, MUSB_OTG);
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       return n;
+}
+static DEVICE_ATTR(mode, 0644, musb_mode_show, musb_mode_store);
+
+static ssize_t
+musb_vbus_store(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t n)
+{
+       struct musb     *musb = dev_to_musb(dev);
+       unsigned long   flags;
+       unsigned long   val;
+
+       if (sscanf(buf, "%lu", &val) < 1) {
+               printk(KERN_ERR "Invalid VBUS timeout ms value\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&musb->lock, flags);
+       musb->a_wait_bcon = val;
+       if (musb->xceiv.state == OTG_STATE_A_WAIT_BCON)
+               musb->is_active = 0;
+       musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val));
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       return n;
+}
+
+static ssize_t
+musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct musb     *musb = dev_to_musb(dev);
+       unsigned long   flags;
+       unsigned long   val;
+       int             vbus;
+
+       spin_lock_irqsave(&musb->lock, flags);
+       val = musb->a_wait_bcon;
+       vbus = musb_platform_get_vbus_status(musb);
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       return sprintf(buf, "Vbus %s, timeout %lu\n",
+                       vbus ? "on" : "off", val);
+}
+static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store);
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+
+/* Gadget drivers can't know that a host is connected so they might want
+ * to start SRP, but users can.  This allows userspace to trigger SRP.
+ */
+static ssize_t
+musb_srp_store(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t n)
+{
+       struct musb     *musb = dev_to_musb(dev);
+       unsigned short  srp;
+
+       if (sscanf(buf, "%hu", &srp) != 1
+                       || (srp != 1)) {
+               printk(KERN_ERR "SRP: Value must be 1\n");
+               return -EINVAL;
+       }
+
+       if (srp == 1)
+               musb_g_wakeup(musb);
+
+       return n;
+}
+static DEVICE_ATTR(srp, 0644, NULL, musb_srp_store);
+
+#endif /* CONFIG_USB_GADGET_MUSB_HDRC */
+
+#endif /* sysfs */
+
+/* Only used to provide driver mode change events */
+static void musb_irq_work(struct work_struct *data)
+{
+       struct musb *musb = container_of(data, struct musb, irq_work);
+       static int old_state;
+
+       if (musb->xceiv.state != old_state) {
+               old_state = musb->xceiv.state;
+               sysfs_notify(&musb->controller->kobj, NULL, "mode");
+       }
+}
+
+/* --------------------------------------------------------------------------
+ * Init support
+ */
+
+static struct musb *__init
+allocate_instance(struct device *dev,
+               struct musb_hdrc_config *config, void __iomem *mbase)
+{
+       struct musb             *musb;
+       struct musb_hw_ep       *ep;
+       int                     epnum;
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       struct usb_hcd  *hcd;
+
+       hcd = usb_create_hcd(&musb_hc_driver, dev, dev->bus_id);
+       if (!hcd)
+               return NULL;
+       /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */
+
+       musb = hcd_to_musb(hcd);
+       INIT_LIST_HEAD(&musb->control);
+       INIT_LIST_HEAD(&musb->in_bulk);
+       INIT_LIST_HEAD(&musb->out_bulk);
+
+       hcd->uses_new_polling = 1;
+
+       musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
+#else
+       musb = kzalloc(sizeof *musb, GFP_KERNEL);
+       if (!musb)
+               return NULL;
+       dev_set_drvdata(dev, musb);
+
+#endif
+
+       musb->mregs = mbase;
+       musb->ctrl_base = mbase;
+       musb->nIrq = -ENODEV;
+       musb->config = config;
+       for (epnum = 0, ep = musb->endpoints;
+                       epnum < musb->config->num_eps;
+                       epnum++, ep++) {
+
+               ep->musb = musb;
+               ep->epnum = epnum;
+       }
+
+       musb->controller = dev;
+       return musb;
+}
+
+static void musb_free(struct musb *musb)
+{
+       /* this has multiple entry modes. it handles fault cleanup after
+        * probe(), where things may be partially set up, as well as rmmod
+        * cleanup after everything's been de-activated.
+        */
+
+#ifdef CONFIG_SYSFS
+       device_remove_file(musb->controller, &dev_attr_mode);
+       device_remove_file(musb->controller, &dev_attr_vbus);
+#ifdef CONFIG_USB_MUSB_OTG
+       device_remove_file(musb->controller, &dev_attr_srp);
+#endif
+#endif
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+       musb_gadget_cleanup(musb);
+#endif
+
+       if (musb->nIrq >= 0) {
+               disable_irq_wake(musb->nIrq);
+               free_irq(musb->nIrq, musb);
+       }
+       if (is_dma_capable() && musb->dma_controller) {
+               struct dma_controller   *c = musb->dma_controller;
+
+               (void) c->stop(c);
+               dma_controller_destroy(c);
+       }
+
+       musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+       musb_platform_exit(musb);
+       musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+
+       if (musb->clock) {
+               clk_disable(musb->clock);
+               clk_put(musb->clock);
+       }
+
+#ifdef CONFIG_USB_MUSB_OTG
+       put_device(musb->xceiv.dev);
+#endif
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       usb_put_hcd(musb_to_hcd(musb));
+#else
+       kfree(musb);
+#endif
+}
+
+/*
+ * Perform generic per-controller initialization.
+ *
+ * @pDevice: the controller (already clocked, etc)
+ * @nIrq: irq
+ * @mregs: virtual address of controller registers,
+ *     not yet corrected for platform-specific offsets
+ */
+static int __init
+musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+{
+       int                     status;
+       struct musb             *musb;
+       struct musb_hdrc_platform_data *plat = dev->platform_data;
+
+       /* The driver might handle more features than the board; OK.
+        * Fail when the board needs a feature that's not enabled.
+        */
+       if (!plat) {
+               dev_dbg(dev, "no platform_data?\n");
+               return -ENODEV;
+       }
+       switch (plat->mode) {
+       case MUSB_HOST:
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+               break;
+#else
+               goto bad_config;
+#endif
+       case MUSB_PERIPHERAL:
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+               break;
+#else
+               goto bad_config;
+#endif
+       case MUSB_OTG:
+#ifdef CONFIG_USB_MUSB_OTG
+               break;
+#else
+bad_config:
+#endif
+       default:
+               dev_err(dev, "incompatible Kconfig role setting\n");
+               return -EINVAL;
+       }
+
+       /* allocate */
+       musb = allocate_instance(dev, plat->config, ctrl);
+       if (!musb)
+               return -ENOMEM;
+
+       spin_lock_init(&musb->lock);
+       musb->board_mode = plat->mode;
+       musb->board_set_power = plat->set_power;
+       musb->set_clock = plat->set_clock;
+       musb->min_power = plat->min_power;
+
+       /* Clock usage is chip-specific ... functional clock (DaVinci,
+        * OMAP2430), or PHY ref (some TUSB6010 boards).  All this core
+        * code does is make sure a clock handle is available; platform
+        * code manages it during start/stop and suspend/resume.
+        */
+       if (plat->clock) {
+               musb->clock = clk_get(dev, plat->clock);
+               if (IS_ERR(musb->clock)) {
+                       status = PTR_ERR(musb->clock);
+                       musb->clock = NULL;
+                       goto fail;
+               }
+       }
+
+       /* assume vbus is off */
+
+       /* platform adjusts musb->mregs and musb->isr if needed,
+        * and activates clocks
+        */
+       musb->isr = generic_interrupt;
+       status = musb_platform_init(musb);
+
+       if (status < 0)
+               goto fail;
+       if (!musb->isr) {
+               status = -ENODEV;
+               goto fail2;
+       }
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+       if (use_dma && dev->dma_mask) {
+               struct dma_controller   *c;
+
+               c = dma_controller_create(musb, musb->mregs);
+               musb->dma_controller = c;
+               if (c)
+                       (void) c->start(c);
+       }
+#endif
+       /* ideally this would be abstracted in platform setup */
+       if (!is_dma_capable() || !musb->dma_controller)
+               dev->dma_mask = NULL;
+
+       /* be sure interrupts are disabled before connecting ISR */
+       musb_platform_disable(musb);
+       musb_generic_disable(musb);
+
+       /* setup musb parts of the core (especially endpoints) */
+       status = musb_core_init(plat->config->multipoint
+                       ? MUSB_CONTROLLER_MHDRC
+                       : MUSB_CONTROLLER_HDRC, musb);
+       if (status < 0)
+               goto fail2;
+
+       /* Init IRQ workqueue before request_irq */
+       INIT_WORK(&musb->irq_work, musb_irq_work);
+
+       /* attach to the IRQ */
+       if (request_irq(nIrq, musb->isr, 0, dev->bus_id, musb)) {
+               dev_err(dev, "request_irq %d failed!\n", nIrq);
+               status = -ENODEV;
+               goto fail2;
+       }
+       musb->nIrq = nIrq;
+/* FIXME this handles wakeup irqs wrong */
+       if (enable_irq_wake(nIrq) == 0)
+               device_init_wakeup(dev, 1);
+
+       pr_info("%s: USB %s mode controller at %p using %s, IRQ %d\n",
+                       musb_driver_name,
+                       ({char *s;
+                       switch (musb->board_mode) {
+                       case MUSB_HOST:         s = "Host"; break;
+                       case MUSB_PERIPHERAL:   s = "Peripheral"; break;
+                       default:                s = "OTG"; break;
+                       }; s; }),
+                       ctrl,
+                       (is_dma_capable() && musb->dma_controller)
+                               ? "DMA" : "PIO",
+                       musb->nIrq);
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       /* host side needs more setup, except for no-host modes */
+       if (musb->board_mode != MUSB_PERIPHERAL) {
+               struct usb_hcd  *hcd = musb_to_hcd(musb);
+
+               if (musb->board_mode == MUSB_OTG)
+                       hcd->self.otg_port = 1;
+               musb->xceiv.host = &hcd->self;
+               hcd->power_budget = 2 * (plat->power ? : 250);
+       }
+#endif                         /* CONFIG_USB_MUSB_HDRC_HCD */
+
+       /* For the host-only role, we can activate right away.
+        * (We expect the ID pin to be forcibly grounded!!)
+        * Otherwise, wait till the gadget driver hooks up.
+        */
+       if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
+               MUSB_HST_MODE(musb);
+               musb->xceiv.default_a = 1;
+               musb->xceiv.state = OTG_STATE_A_IDLE;
+
+               status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
+
+               DBG(1, "%s mode, status %d, devctl %02x %c\n",
+                       "HOST", status,
+                       musb_readb(musb->mregs, MUSB_DEVCTL),
+                       (musb_readb(musb->mregs, MUSB_DEVCTL)
+                                       & MUSB_DEVCTL_BDEVICE
+                               ? 'B' : 'A'));
+
+       } else /* peripheral is enabled */ {
+               MUSB_DEV_MODE(musb);
+               musb->xceiv.default_a = 0;
+               musb->xceiv.state = OTG_STATE_B_IDLE;
+
+               status = musb_gadget_setup(musb);
+
+               DBG(1, "%s mode, status %d, dev%02x\n",
+                       is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",
+                       status,
+                       musb_readb(musb->mregs, MUSB_DEVCTL));
+
+       }
+
+       if (status == 0)
+               musb_debug_create("driver/musb_hdrc", musb);
+       else {
+fail:
+               if (musb->clock)
+                       clk_put(musb->clock);
+               device_init_wakeup(dev, 0);
+               musb_free(musb);
+               return status;
+       }
+
+#ifdef CONFIG_SYSFS
+       status = device_create_file(dev, &dev_attr_mode);
+       status = device_create_file(dev, &dev_attr_vbus);
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+       status = device_create_file(dev, &dev_attr_srp);
+#endif /* CONFIG_USB_GADGET_MUSB_HDRC */
+       status = 0;
+#endif
+
+       return status;
+
+fail2:
+       musb_platform_exit(musb);
+       goto fail;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just
+ * bridge to a platform device; this driver then suffices.
+ */
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+static u64     *orig_dma_mask;
+#endif
+
+static int __init musb_probe(struct platform_device *pdev)
+{
+       struct device   *dev = &pdev->dev;
+       int             irq = platform_get_irq(pdev, 0);
+       struct resource *iomem;
+       void __iomem    *base;
+
+       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!iomem || irq == 0)
+               return -ENODEV;
+
+       base = ioremap(iomem->start, iomem->end - iomem->start + 1);
+       if (!base) {
+               dev_err(dev, "ioremap failed\n");
+               return -ENOMEM;
+       }
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+       /* clobbered by use_dma=n */
+       orig_dma_mask = dev->dma_mask;
+#endif
+       return musb_init_controller(dev, irq, base);
+}
+
+static int __devexit musb_remove(struct platform_device *pdev)
+{
+       struct musb     *musb = dev_to_musb(&pdev->dev);
+       void __iomem    *ctrl_base = musb->ctrl_base;
+
+       /* this gets called on rmmod.
+        *  - Host mode: host may still be active
+        *  - Peripheral mode: peripheral is deactivated (or never-activated)
+        *  - OTG mode: both roles are deactivated (or never-activated)
+        */
+       musb_shutdown(pdev);
+       musb_debug_delete("driver/musb_hdrc", musb);
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       if (musb->board_mode == MUSB_HOST)
+               usb_remove_hcd(musb_to_hcd(musb));
+#endif
+       musb_free(musb);
+       iounmap(ctrl_base);
+       device_init_wakeup(&pdev->dev, 0);
+#ifndef CONFIG_MUSB_PIO_ONLY
+       pdev->dev.dma_mask = orig_dma_mask;
+#endif
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int musb_suspend(struct platform_device *pdev, pm_message_t message)
+{
+       unsigned long   flags;
+       struct musb     *musb = dev_to_musb(&pdev->dev);
+
+       if (!musb->clock)
+               return 0;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       if (is_peripheral_active(musb)) {
+               /* FIXME force disconnect unless we know USB will wake
+                * the system up quickly enough to respond ...
+                */
+       } else if (is_host_active(musb)) {
+               /* we know all the children are suspended; sometimes
+                * they will even be wakeup-enabled.
+                */
+       }
+
+       if (musb->set_clock)
+               musb->set_clock(musb->clock, 0);
+       else
+               clk_disable(musb->clock);
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return 0;
+}
+
+static int musb_resume(struct platform_device *pdev)
+{
+       unsigned long   flags;
+       struct musb     *musb = dev_to_musb(&pdev->dev);
+
+       if (!musb->clock)
+               return 0;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       if (musb->set_clock)
+               musb->set_clock(musb->clock, 1);
+       else
+               clk_enable(musb->clock);
+
+       /* for static cmos like DaVinci, register values were preserved
+        * unless for some reason the whole soc powered down and we're
+        * not treating that as a whole-system restart (e.g. swsusp)
+        */
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return 0;
+}
+
+#else
+#define        musb_suspend    NULL
+#define        musb_resume     NULL
+#endif
+
+static struct platform_driver musb_driver = {
+       .driver = {
+               .name           = (char *)musb_driver_name,
+               .bus            = &platform_bus_type,
+               .owner          = THIS_MODULE,
+       },
+       .remove         = __devexit_p(musb_remove),
+       .shutdown       = musb_shutdown,
+       .suspend        = musb_suspend,
+       .resume         = musb_resume,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init musb_init(void)
+{
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       if (usb_disabled())
+               return 0;
+#endif
+
+       pr_info("%s: version " MUSB_VERSION ", "
+#ifdef CONFIG_MUSB_PIO_ONLY
+               "pio"
+#elif defined(CONFIG_USB_TI_CPPI_DMA)
+               "cppi-dma"
+#elif defined(CONFIG_USB_INVENTRA_DMA)
+               "musb-dma"
+#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
+               "tusb-omap-dma"
+#else
+               "?dma?"
+#endif
+               ", "
+#ifdef CONFIG_USB_MUSB_OTG
+               "otg (peripheral+host)"
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+               "peripheral"
+#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+               "host"
+#endif
+               ", debug=%d\n",
+               musb_driver_name, debug);
+       return platform_driver_probe(&musb_driver, musb_probe);
+}
+
+/* make us init after usbcore and before usb
+ * gadget and host-side drivers start to register
+ */
+subsys_initcall(musb_init);
+
+static void __exit musb_cleanup(void)
+{
+       platform_driver_unregister(&musb_driver);
+}
+module_exit(musb_cleanup);
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
new file mode 100644 (file)
index 0000000..eade46d
--- /dev/null
@@ -0,0 +1,507 @@
+/*
+ * MUSB OTG driver defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_CORE_H__
+#define __MUSB_CORE_H__
+
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/musb.h>
+
+struct musb;
+struct musb_hw_ep;
+struct musb_ep;
+
+
+#include "musb_debug.h"
+#include "musb_dma.h"
+
+#include "musb_io.h"
+#include "musb_regs.h"
+
+#include "musb_gadget.h"
+#include "../core/hcd.h"
+#include "musb_host.h"
+
+
+
+#ifdef CONFIG_USB_MUSB_OTG
+
+#define        is_peripheral_enabled(musb)     ((musb)->board_mode != MUSB_HOST)
+#define        is_host_enabled(musb)           ((musb)->board_mode != MUSB_PERIPHERAL)
+#define        is_otg_enabled(musb)            ((musb)->board_mode == MUSB_OTG)
+
+/* NOTE:  otg and peripheral-only state machines start at B_IDLE.
+ * OTG or host-only go to A_IDLE when ID is sensed.
+ */
+#define is_peripheral_active(m)                (!(m)->is_host)
+#define is_host_active(m)              ((m)->is_host)
+
+#else
+#define        is_peripheral_enabled(musb)     is_peripheral_capable()
+#define        is_host_enabled(musb)           is_host_capable()
+#define        is_otg_enabled(musb)            0
+
+#define        is_peripheral_active(musb)      is_peripheral_capable()
+#define        is_host_active(musb)            is_host_capable()
+#endif
+
+#if defined(CONFIG_USB_MUSB_OTG) || defined(CONFIG_USB_MUSB_PERIPHERAL)
+/* for some reason, the "select USB_GADGET_MUSB_HDRC" doesn't always
+ * override that choice selection (often USB_GADGET_DUMMY_HCD).
+ */
+#ifndef CONFIG_USB_GADGET_MUSB_HDRC
+#error bogus Kconfig output ... select CONFIG_USB_GADGET_MUSB_HDRC
+#endif
+#endif /* need MUSB gadget selection */
+
+
+#ifdef CONFIG_PROC_FS
+#include <linux/fs.h>
+#define MUSB_CONFIG_PROC_FS
+#endif
+
+/****************************** PERIPHERAL ROLE *****************************/
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+
+#define        is_peripheral_capable() (1)
+
+extern irqreturn_t musb_g_ep0_irq(struct musb *);
+extern void musb_g_tx(struct musb *, u8);
+extern void musb_g_rx(struct musb *, u8);
+extern void musb_g_reset(struct musb *);
+extern void musb_g_suspend(struct musb *);
+extern void musb_g_resume(struct musb *);
+extern void musb_g_wakeup(struct musb *);
+extern void musb_g_disconnect(struct musb *);
+
+#else
+
+#define        is_peripheral_capable() (0)
+
+static inline irqreturn_t musb_g_ep0_irq(struct musb *m) { return IRQ_NONE; }
+static inline void musb_g_reset(struct musb *m) {}
+static inline void musb_g_suspend(struct musb *m) {}
+static inline void musb_g_resume(struct musb *m) {}
+static inline void musb_g_wakeup(struct musb *m) {}
+static inline void musb_g_disconnect(struct musb *m) {}
+
+#endif
+
+/****************************** HOST ROLE ***********************************/
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+
+#define        is_host_capable()       (1)
+
+extern irqreturn_t musb_h_ep0_irq(struct musb *);
+extern void musb_host_tx(struct musb *, u8);
+extern void musb_host_rx(struct musb *, u8);
+
+#else
+
+#define        is_host_capable()       (0)
+
+static inline irqreturn_t musb_h_ep0_irq(struct musb *m) { return IRQ_NONE; }
+static inline void musb_host_tx(struct musb *m, u8 e) {}
+static inline void musb_host_rx(struct musb *m, u8 e) {}
+
+#endif
+
+
+/****************************** CONSTANTS ********************************/
+
+#ifndef MUSB_C_NUM_EPS
+#define MUSB_C_NUM_EPS ((u8)16)
+#endif
+
+#ifndef MUSB_MAX_END0_PACKET
+#define MUSB_MAX_END0_PACKET ((u16)MUSB_EP0_FIFOSIZE)
+#endif
+
+/* host side ep0 states */
+enum musb_h_ep0_state {
+       MUSB_EP0_IDLE,
+       MUSB_EP0_START,                 /* expect ack of setup */
+       MUSB_EP0_IN,                    /* expect IN DATA */
+       MUSB_EP0_OUT,                   /* expect ack of OUT DATA */
+       MUSB_EP0_STATUS,                /* expect ack of STATUS */
+} __attribute__ ((packed));
+
+/* peripheral side ep0 states */
+enum musb_g_ep0_state {
+       MUSB_EP0_STAGE_SETUP,           /* idle, waiting for setup */
+       MUSB_EP0_STAGE_TX,              /* IN data */
+       MUSB_EP0_STAGE_RX,              /* OUT data */
+       MUSB_EP0_STAGE_STATUSIN,        /* (after OUT data) */
+       MUSB_EP0_STAGE_STATUSOUT,       /* (after IN data) */
+       MUSB_EP0_STAGE_ACKWAIT,         /* after zlp, before statusin */
+} __attribute__ ((packed));
+
+/* OTG protocol constants */
+#define OTG_TIME_A_WAIT_VRISE  100             /* msec (max) */
+#define OTG_TIME_A_WAIT_BCON   0               /* 0=infinite; min 1000 msec */
+#define OTG_TIME_A_IDLE_BDIS   200             /* msec (min) */
+
+/*************************** REGISTER ACCESS ********************************/
+
+/* Endpoint registers (other than dynfifo setup) can be accessed either
+ * directly with the "flat" model, or after setting up an index register.
+ */
+
+#if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_ARCH_OMAP2430) \
+               || defined(CONFIG_ARCH_OMAP3430)
+/* REVISIT indexed access seemed to
+ * misbehave (on DaVinci) for at least peripheral IN ...
+ */
+#define        MUSB_FLAT_REG
+#endif
+
+/* TUSB mapping: "flat" plus ep0 special cases */
+#if    defined(CONFIG_USB_TUSB6010)
+#define musb_ep_select(_mbase, _epnum) \
+       musb_writeb((_mbase), MUSB_INDEX, (_epnum))
+#define        MUSB_EP_OFFSET                  MUSB_TUSB_OFFSET
+
+/* "flat" mapping: each endpoint has its own i/o address */
+#elif  defined(MUSB_FLAT_REG)
+#define musb_ep_select(_mbase, _epnum) (((void)(_mbase)), ((void)(_epnum)))
+#define        MUSB_EP_OFFSET                  MUSB_FLAT_OFFSET
+
+/* "indexed" mapping: INDEX register controls register bank select */
+#else
+#define musb_ep_select(_mbase, _epnum) \
+       musb_writeb((_mbase), MUSB_INDEX, (_epnum))
+#define        MUSB_EP_OFFSET                  MUSB_INDEXED_OFFSET
+#endif
+
+/****************************** FUNCTIONS ********************************/
+
+#define MUSB_HST_MODE(_musb)\
+       { (_musb)->is_host = true; }
+#define MUSB_DEV_MODE(_musb) \
+       { (_musb)->is_host = false; }
+
+#define test_devctl_hst_mode(_x) \
+       (musb_readb((_x)->mregs, MUSB_DEVCTL)&MUSB_DEVCTL_HM)
+
+#define MUSB_MODE(musb) ((musb)->is_host ? "Host" : "Peripheral")
+
+/******************************** TYPES *************************************/
+
+/*
+ * struct musb_hw_ep - endpoint hardware (bidirectional)
+ *
+ * Ordered slightly for better cacheline locality.
+ */
+struct musb_hw_ep {
+       struct musb             *musb;
+       void __iomem            *fifo;
+       void __iomem            *regs;
+
+#ifdef CONFIG_USB_TUSB6010
+       void __iomem            *conf;
+#endif
+
+       /* index in musb->endpoints[]  */
+       u8                      epnum;
+
+       /* hardware configuration, possibly dynamic */
+       bool                    is_shared_fifo;
+       bool                    tx_double_buffered;
+       bool                    rx_double_buffered;
+       u16                     max_packet_sz_tx;
+       u16                     max_packet_sz_rx;
+
+       struct dma_channel      *tx_channel;
+       struct dma_channel      *rx_channel;
+
+#ifdef CONFIG_USB_TUSB6010
+       /* TUSB has "asynchronous" and "synchronous" dma modes */
+       dma_addr_t              fifo_async;
+       dma_addr_t              fifo_sync;
+       void __iomem            *fifo_sync_va;
+#endif
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       void __iomem            *target_regs;
+
+       /* currently scheduled peripheral endpoint */
+       struct musb_qh          *in_qh;
+       struct musb_qh          *out_qh;
+
+       u8                      rx_reinit;
+       u8                      tx_reinit;
+#endif
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+       /* peripheral side */
+       struct musb_ep          ep_in;                  /* TX */
+       struct musb_ep          ep_out;                 /* RX */
+#endif
+};
+
+static inline struct usb_request *next_in_request(struct musb_hw_ep *hw_ep)
+{
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+       return next_request(&hw_ep->ep_in);
+#else
+       return NULL;
+#endif
+}
+
+static inline struct usb_request *next_out_request(struct musb_hw_ep *hw_ep)
+{
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+       return next_request(&hw_ep->ep_out);
+#else
+       return NULL;
+#endif
+}
+
+/*
+ * struct musb - Driver instance data.
+ */
+struct musb {
+       /* device lock */
+       spinlock_t              lock;
+       struct clk              *clock;
+       irqreturn_t             (*isr)(int, void *);
+       struct work_struct      irq_work;
+
+/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
+#define MUSB_PORT_STAT_RESUME  (1 << 31)
+
+       u32                     port1_status;
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       unsigned long           rh_timer;
+
+       enum musb_h_ep0_state   ep0_stage;
+
+       /* bulk traffic normally dedicates endpoint hardware, and each
+        * direction has its own ring of host side endpoints.
+        * we try to progress the transfer at the head of each endpoint's
+        * queue until it completes or NAKs too much; then we try the next
+        * endpoint.
+        */
+       struct musb_hw_ep       *bulk_ep;
+
+       struct list_head        control;        /* of musb_qh */
+       struct list_head        in_bulk;        /* of musb_qh */
+       struct list_head        out_bulk;       /* of musb_qh */
+       struct musb_qh          *periodic[32];  /* tree of interrupt+iso */
+#endif
+
+       /* called with IRQs blocked; ON/nonzero implies starting a session,
+        * and waiting at least a_wait_vrise_tmout.
+        */
+       void                    (*board_set_vbus)(struct musb *, int is_on);
+
+       struct dma_controller   *dma_controller;
+
+       struct device           *controller;
+       void __iomem            *ctrl_base;
+       void __iomem            *mregs;
+
+#ifdef CONFIG_USB_TUSB6010
+       dma_addr_t              async;
+       dma_addr_t              sync;
+       void __iomem            *sync_va;
+#endif
+
+       /* passed down from chip/board specific irq handlers */
+       u8                      int_usb;
+       u16                     int_rx;
+       u16                     int_tx;
+
+       struct otg_transceiver  xceiv;
+
+       int nIrq;
+
+       struct musb_hw_ep        endpoints[MUSB_C_NUM_EPS];
+#define control_ep             endpoints
+
+#define VBUSERR_RETRY_COUNT    3
+       u16                     vbuserr_retry;
+       u16 epmask;
+       u8 nr_endpoints;
+
+       u8 board_mode;          /* enum musb_mode */
+       int                     (*board_set_power)(int state);
+
+       int                     (*set_clock)(struct clk *clk, int is_active);
+
+       u8                      min_power;      /* vbus for periph, in mA/2 */
+
+       bool                    is_host;
+
+       int                     a_wait_bcon;    /* VBUS timeout in msecs */
+       unsigned long           idle_timeout;   /* Next timeout in jiffies */
+
+       /* active means connected and not suspended */
+       unsigned                is_active:1;
+
+       unsigned is_multipoint:1;
+       unsigned ignore_disconnect:1;   /* during bus resets */
+
+#ifdef C_MP_TX
+       unsigned bulk_split:1;
+#define        can_bulk_split(musb,type) \
+               (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_split)
+#else
+#define        can_bulk_split(musb, type)      0
+#endif
+
+#ifdef C_MP_RX
+       unsigned bulk_combine:1;
+#define        can_bulk_combine(musb,type) \
+               (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine)
+#else
+#define        can_bulk_combine(musb, type)    0
+#endif
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+       /* is_suspended means USB B_PERIPHERAL suspend */
+       unsigned                is_suspended:1;
+
+       /* may_wakeup means remote wakeup is enabled */
+       unsigned                may_wakeup:1;
+
+       /* is_self_powered is reported in device status and the
+        * config descriptor.  is_bus_powered means B_PERIPHERAL
+        * draws some VBUS current; both can be true.
+        */
+       unsigned                is_self_powered:1;
+       unsigned                is_bus_powered:1;
+
+       unsigned                set_address:1;
+       unsigned                test_mode:1;
+       unsigned                softconnect:1;
+
+       u8                      address;
+       u8                      test_mode_nr;
+       u16                     ackpend;                /* ep0 */
+       enum musb_g_ep0_state   ep0_state;
+       struct usb_gadget       g;                      /* the gadget */
+       struct usb_gadget_driver *gadget_driver;        /* its driver */
+#endif
+
+       struct musb_hdrc_config *config;
+
+#ifdef MUSB_CONFIG_PROC_FS
+       struct proc_dir_entry *proc_entry;
+#endif
+};
+
+static inline void musb_set_vbus(struct musb *musb, int is_on)
+{
+       musb->board_set_vbus(musb, is_on);
+}
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+static inline struct musb *gadget_to_musb(struct usb_gadget *g)
+{
+       return container_of(g, struct musb, g);
+}
+#endif
+
+
+/***************************** Glue it together *****************************/
+
+extern const char musb_driver_name[];
+
+extern void musb_start(struct musb *musb);
+extern void musb_stop(struct musb *musb);
+
+extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
+extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
+
+extern void musb_load_testpacket(struct musb *);
+
+extern irqreturn_t musb_interrupt(struct musb *);
+
+extern void musb_platform_enable(struct musb *musb);
+extern void musb_platform_disable(struct musb *musb);
+
+extern void musb_hnp_stop(struct musb *musb);
+
+extern void musb_platform_set_mode(struct musb *musb, u8 musb_mode);
+
+#if defined(CONFIG_USB_TUSB6010) || \
+       defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout);
+#else
+#define musb_platform_try_idle(x, y)           do {} while (0)
+#endif
+
+#ifdef CONFIG_USB_TUSB6010
+extern int musb_platform_get_vbus_status(struct musb *musb);
+#else
+#define musb_platform_get_vbus_status(x)       0
+#endif
+
+extern int __init musb_platform_init(struct musb *musb);
+extern int musb_platform_exit(struct musb *musb);
+
+/*-------------------------- ProcFS definitions ---------------------*/
+
+struct proc_dir_entry;
+
+#if (MUSB_DEBUG > 0) && defined(MUSB_CONFIG_PROC_FS)
+extern struct proc_dir_entry *musb_debug_create(char *name, struct musb *data);
+extern void musb_debug_delete(char *name, struct musb *data);
+
+#else
+static inline struct proc_dir_entry *
+musb_debug_create(char *name, struct musb *data)
+{
+       return NULL;
+}
+static inline void musb_debug_delete(char *name, struct musb *data)
+{
+}
+#endif
+
+#endif /* __MUSB_CORE_H__ */
diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h
new file mode 100644 (file)
index 0000000..3bdb311
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * MUSB OTG driver debug defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_LINUX_DEBUG_H__
+#define __MUSB_LINUX_DEBUG_H__
+
+#define yprintk(facility, format, args...) \
+       do { printk(facility "%s %d: " format , \
+       __func__, __LINE__ , ## args); } while (0)
+#define WARNING(fmt, args...) yprintk(KERN_WARNING, fmt, ## args)
+#define INFO(fmt, args...) yprintk(KERN_INFO, fmt, ## args)
+#define ERR(fmt, args...) yprintk(KERN_ERR, fmt, ## args)
+
+#define xprintk(level, facility, format, args...) do { \
+       if (_dbg_level(level)) { \
+               printk(facility "%s %d: " format , \
+                               __func__, __LINE__ , ## args); \
+       } } while (0)
+
+#if MUSB_DEBUG > 0
+extern unsigned debug;
+#else
+#define debug  0
+#endif
+
+static inline int _dbg_level(unsigned l)
+{
+       return debug >= l;
+}
+
+#define DBG(level, fmt, args...) xprintk(level, KERN_DEBUG, fmt, ## args)
+
+extern const char *otg_state_string(struct musb *);
+
+#endif                         /*  __MUSB_LINUX_DEBUG_H__ */
diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
new file mode 100644 (file)
index 0000000..0a2c4e3
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * MUSB OTG driver DMA controller abstraction
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_DMA_H__
+#define __MUSB_DMA_H__
+
+struct musb_hw_ep;
+
+/*
+ * DMA Controller Abstraction
+ *
+ * DMA Controllers are abstracted to allow use of a variety of different
+ * implementations of DMA, as allowed by the Inventra USB cores.  On the
+ * host side, usbcore sets up the DMA mappings and flushes caches; on the
+ * peripheral side, the gadget controller driver does.  Responsibilities
+ * of a DMA controller driver include:
+ *
+ *  - Handling the details of moving multiple USB packets
+ *    in cooperation with the Inventra USB core, including especially
+ *    the correct RX side treatment of short packets and buffer-full
+ *    states (both of which terminate transfers).
+ *
+ *  - Knowing the correlation between dma channels and the
+ *    Inventra core's local endpoint resources and data direction.
+ *
+ *  - Maintaining a list of allocated/available channels.
+ *
+ *  - Updating channel status on interrupts,
+ *    whether shared with the Inventra core or separate.
+ */
+
+#define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+#define        is_dma_capable()        (1)
+#else
+#define        is_dma_capable()        (0)
+#endif
+
+#ifdef CONFIG_USB_TI_CPPI_DMA
+#define        is_cppi_enabled()       1
+#else
+#define        is_cppi_enabled()       0
+#endif
+
+#ifdef CONFIG_USB_TUSB_OMAP_DMA
+#define tusb_dma_omap()                        1
+#else
+#define tusb_dma_omap()                        0
+#endif
+
+/*
+ * DMA channel status ... updated by the dma controller driver whenever that
+ * status changes, and protected by the overall controller spinlock.
+ */
+enum dma_channel_status {
+       /* unallocated */
+       MUSB_DMA_STATUS_UNKNOWN,
+       /* allocated ... but not busy, no errors */
+       MUSB_DMA_STATUS_FREE,
+       /* busy ... transactions are active */
+       MUSB_DMA_STATUS_BUSY,
+       /* transaction(s) aborted due to ... dma or memory bus error */
+       MUSB_DMA_STATUS_BUS_ABORT,
+       /* transaction(s) aborted due to ... core error or USB fault */
+       MUSB_DMA_STATUS_CORE_ABORT
+};
+
+struct dma_controller;
+
+/**
+ * struct dma_channel - A DMA channel.
+ * @private_data: channel-private data
+ * @max_len: the maximum number of bytes the channel can move in one
+ *     transaction (typically representing many USB maximum-sized packets)
+ * @actual_len: how many bytes have been transferred
+ * @status: current channel status (updated e.g. on interrupt)
+ * @desired_mode: true if mode 1 is desired; false if mode 0 is desired
+ *
+ * channels are associated with an endpoint for the duration of at least
+ * one usb transfer.
+ */
+struct dma_channel {
+       void                    *private_data;
+       /* FIXME not void* private_data, but a dma_controller * */
+       size_t                  max_len;
+       size_t                  actual_len;
+       enum dma_channel_status status;
+       bool                    desired_mode;
+};
+
+/*
+ * dma_channel_status - return status of dma channel
+ * @c: the channel
+ *
+ * Returns the software's view of the channel status.  If that status is BUSY
+ * then it's possible that the hardware has completed (or aborted) a transfer,
+ * so the driver needs to update that status.
+ */
+static inline enum dma_channel_status
+dma_channel_status(struct dma_channel *c)
+{
+       return (is_dma_capable() && c) ? c->status : MUSB_DMA_STATUS_UNKNOWN;
+}
+
+/**
+ * struct dma_controller - A DMA Controller.
+ * @start: call this to start a DMA controller;
+ *     return 0 on success, else negative errno
+ * @stop: call this to stop a DMA controller
+ *     return 0 on success, else negative errno
+ * @channel_alloc: call this to allocate a DMA channel
+ * @channel_release: call this to release a DMA channel
+ * @channel_abort: call this to abort a pending DMA transaction,
+ *     returning it to FREE (but allocated) state
+ *
+ * Controllers manage dma channels.
+ */
+struct dma_controller {
+       int                     (*start)(struct dma_controller *);
+       int                     (*stop)(struct dma_controller *);
+       struct dma_channel      *(*channel_alloc)(struct dma_controller *,
+                                       struct musb_hw_ep *, u8 is_tx);
+       void                    (*channel_release)(struct dma_channel *);
+       int                     (*channel_program)(struct dma_channel *channel,
+                                                       u16 maxpacket, u8 mode,
+                                                       dma_addr_t dma_addr,
+                                                       u32 length);
+       int                     (*channel_abort)(struct dma_channel *);
+};
+
+/* called after channel_program(), may indicate a fault */
+extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit);
+
+
+extern struct dma_controller *__init
+dma_controller_create(struct musb *, void __iomem *);
+
+extern void dma_controller_destroy(struct dma_controller *);
+
+#endif /* __MUSB_DMA_H__ */
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
new file mode 100644 (file)
index 0000000..d6a802c
--- /dev/null
@@ -0,0 +1,2031 @@
+/*
+ * MUSB OTG driver peripheral support
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/moduleparam.h>
+#include <linux/stat.h>
+#include <linux/dma-mapping.h>
+
+#include "musb_core.h"
+
+
+/* MUSB PERIPHERAL status 3-mar-2006:
+ *
+ * - EP0 seems solid.  It passes both USBCV and usbtest control cases.
+ *   Minor glitches:
+ *
+ *     + remote wakeup to Linux hosts work, but saw USBCV failures;
+ *       in one test run (operator error?)
+ *     + endpoint halt tests -- in both usbtest and usbcv -- seem
+ *       to break when dma is enabled ... is something wrongly
+ *       clearing SENDSTALL?
+ *
+ * - Mass storage behaved ok when last tested.  Network traffic patterns
+ *   (with lots of short transfers etc) need retesting; they turn up the
+ *   worst cases of the DMA, since short packets are typical but are not
+ *   required.
+ *
+ * - TX/IN
+ *     + both pio and dma behave in with network and g_zero tests
+ *     + no cppi throughput issues other than no-hw-queueing
+ *     + failed with FLAT_REG (DaVinci)
+ *     + seems to behave with double buffering, PIO -and- CPPI
+ *     + with gadgetfs + AIO, requests got lost?
+ *
+ * - RX/OUT
+ *     + both pio and dma behave in with network and g_zero tests
+ *     + dma is slow in typical case (short_not_ok is clear)
+ *     + double buffering ok with PIO
+ *     + double buffering *FAILS* with CPPI, wrong data bytes sometimes
+ *     + request lossage observed with gadgetfs
+ *
+ * - ISO not tested ... might work, but only weakly isochronous
+ *
+ * - Gadget driver disabling of softconnect during bind() is ignored; so
+ *   drivers can't hold off host requests until userspace is ready.
+ *   (Workaround:  they can turn it off later.)
+ *
+ * - PORTABILITY (assumes PIO works):
+ *     + DaVinci, basically works with cppi dma
+ *     + OMAP 2430, ditto with mentor dma
+ *     + TUSB 6010, platform-specific dma in the works
+ */
+
+/* ----------------------------------------------------------------------- */
+
+/*
+ * Immediately complete a request.
+ *
+ * @param request the request to complete
+ * @param status the status to complete the request with
+ * Context: controller locked, IRQs blocked.
+ */
+void musb_g_giveback(
+       struct musb_ep          *ep,
+       struct usb_request      *request,
+       int                     status)
+__releases(ep->musb->lock)
+__acquires(ep->musb->lock)
+{
+       struct musb_request     *req;
+       struct musb             *musb;
+       int                     busy = ep->busy;
+
+       req = to_musb_request(request);
+
+       list_del(&request->list);
+       if (req->request.status == -EINPROGRESS)
+               req->request.status = status;
+       musb = req->musb;
+
+       ep->busy = 1;
+       spin_unlock(&musb->lock);
+       if (is_dma_capable()) {
+               if (req->mapped) {
+                       dma_unmap_single(musb->controller,
+                                       req->request.dma,
+                                       req->request.length,
+                                       req->tx
+                                               ? DMA_TO_DEVICE
+                                               : DMA_FROM_DEVICE);
+                       req->request.dma = DMA_ADDR_INVALID;
+                       req->mapped = 0;
+               } else if (req->request.dma != DMA_ADDR_INVALID)
+                       dma_sync_single_for_cpu(musb->controller,
+                                       req->request.dma,
+                                       req->request.length,
+                                       req->tx
+                                               ? DMA_TO_DEVICE
+                                               : DMA_FROM_DEVICE);
+       }
+       if (request->status == 0)
+               DBG(5, "%s done request %p,  %d/%d\n",
+                               ep->end_point.name, request,
+                               req->request.actual, req->request.length);
+       else
+               DBG(2, "%s request %p, %d/%d fault %d\n",
+                               ep->end_point.name, request,
+                               req->request.actual, req->request.length,
+                               request->status);
+       req->request.complete(&req->ep->end_point, &req->request);
+       spin_lock(&musb->lock);
+       ep->busy = busy;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/*
+ * Abort requests queued to an endpoint using the status. Synchronous.
+ * caller locked controller and blocked irqs, and selected this ep.
+ */
+static void nuke(struct musb_ep *ep, const int status)
+{
+       struct musb_request     *req = NULL;
+       void __iomem *epio = ep->musb->endpoints[ep->current_epnum].regs;
+
+       ep->busy = 1;
+
+       if (is_dma_capable() && ep->dma) {
+               struct dma_controller   *c = ep->musb->dma_controller;
+               int value;
+               if (ep->is_in) {
+                       musb_writew(epio, MUSB_TXCSR,
+                                       0 | MUSB_TXCSR_FLUSHFIFO);
+                       musb_writew(epio, MUSB_TXCSR,
+                                       0 | MUSB_TXCSR_FLUSHFIFO);
+               } else {
+                       musb_writew(epio, MUSB_RXCSR,
+                                       0 | MUSB_RXCSR_FLUSHFIFO);
+                       musb_writew(epio, MUSB_RXCSR,
+                                       0 | MUSB_RXCSR_FLUSHFIFO);
+               }
+
+               value = c->channel_abort(ep->dma);
+               DBG(value ? 1 : 6, "%s: abort DMA --> %d\n", ep->name, value);
+               c->channel_release(ep->dma);
+               ep->dma = NULL;
+       }
+
+       while (!list_empty(&(ep->req_list))) {
+               req = container_of(ep->req_list.next, struct musb_request,
+                               request.list);
+               musb_g_giveback(ep, &req->request, status);
+       }
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* Data transfers - pure PIO, pure DMA, or mixed mode */
+
+/*
+ * This assumes the separate CPPI engine is responding to DMA requests
+ * from the usb core ... sequenced a bit differently from mentor dma.
+ */
+
+static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
+{
+       if (can_bulk_split(musb, ep->type))
+               return ep->hw_ep->max_packet_sz_tx;
+       else
+               return ep->packet_sz;
+}
+
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+
+/* Peripheral tx (IN) using Mentor DMA works as follows:
+       Only mode 0 is used for transfers <= wPktSize,
+       mode 1 is used for larger transfers,
+
+       One of the following happens:
+       - Host sends IN token which causes an endpoint interrupt
+               -> TxAvail
+                       -> if DMA is currently busy, exit.
+                       -> if queue is non-empty, txstate().
+
+       - Request is queued by the gadget driver.
+               -> if queue was previously empty, txstate()
+
+       txstate()
+               -> start
+                 /\    -> setup DMA
+                 |     (data is transferred to the FIFO, then sent out when
+                 |     IN token(s) are recd from Host.
+                 |             -> DMA interrupt on completion
+                 |                calls TxAvail.
+                 |                   -> stop DMA, ~DmaEenab,
+                 |                   -> set TxPktRdy for last short pkt or zlp
+                 |                   -> Complete Request
+                 |                   -> Continue next request (call txstate)
+                 |___________________________________|
+
+ * Non-Mentor DMA engines can of course work differently, such as by
+ * upleveling from irq-per-packet to irq-per-buffer.
+ */
+
+#endif
+
+/*
+ * An endpoint is transmitting data. This can be called either from
+ * the IRQ routine or from ep.queue() to kickstart a request on an
+ * endpoint.
+ *
+ * Context: controller locked, IRQs blocked, endpoint selected
+ */
+static void txstate(struct musb *musb, struct musb_request *req)
+{
+       u8                      epnum = req->epnum;
+       struct musb_ep          *musb_ep;
+       void __iomem            *epio = musb->endpoints[epnum].regs;
+       struct usb_request      *request;
+       u16                     fifo_count = 0, csr;
+       int                     use_dma = 0;
+
+       musb_ep = req->ep;
+
+       /* we shouldn't get here while DMA is active ... but we do ... */
+       if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) {
+               DBG(4, "dma pending...\n");
+               return;
+       }
+
+       /* read TXCSR before */
+       csr = musb_readw(epio, MUSB_TXCSR);
+
+       request = &req->request;
+       fifo_count = min(max_ep_writesize(musb, musb_ep),
+                       (int)(request->length - request->actual));
+
+       if (csr & MUSB_TXCSR_TXPKTRDY) {
+               DBG(5, "%s old packet still ready , txcsr %03x\n",
+                               musb_ep->end_point.name, csr);
+               return;
+       }
+
+       if (csr & MUSB_TXCSR_P_SENDSTALL) {
+               DBG(5, "%s stalling, txcsr %03x\n",
+                               musb_ep->end_point.name, csr);
+               return;
+       }
+
+       DBG(4, "hw_ep%d, maxpacket %d, fifo count %d, txcsr %03x\n",
+                       epnum, musb_ep->packet_sz, fifo_count,
+                       csr);
+
+#ifndef        CONFIG_MUSB_PIO_ONLY
+       if (is_dma_capable() && musb_ep->dma) {
+               struct dma_controller   *c = musb->dma_controller;
+
+               use_dma = (request->dma != DMA_ADDR_INVALID);
+
+               /* MUSB_TXCSR_P_ISO is still set correctly */
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+               {
+                       size_t request_size;
+
+                       /* setup DMA, then program endpoint CSR */
+                       request_size = min(request->length,
+                                               musb_ep->dma->max_len);
+                       if (request_size <= musb_ep->packet_sz)
+                               musb_ep->dma->desired_mode = 0;
+                       else
+                               musb_ep->dma->desired_mode = 1;
+
+                       use_dma = use_dma && c->channel_program(
+                                       musb_ep->dma, musb_ep->packet_sz,
+                                       musb_ep->dma->desired_mode,
+                                       request->dma, request_size);
+                       if (use_dma) {
+                               if (musb_ep->dma->desired_mode == 0) {
+                                       /* ASSERT: DMAENAB is clear */
+                                       csr &= ~(MUSB_TXCSR_AUTOSET |
+                                                       MUSB_TXCSR_DMAMODE);
+                                       csr |= (MUSB_TXCSR_DMAENAB |
+                                                       MUSB_TXCSR_MODE);
+                                       /* against programming guide */
+                               } else
+                                       csr |= (MUSB_TXCSR_AUTOSET
+                                                       | MUSB_TXCSR_DMAENAB
+                                                       | MUSB_TXCSR_DMAMODE
+                                                       | MUSB_TXCSR_MODE);
+
+                               csr &= ~MUSB_TXCSR_P_UNDERRUN;
+                               musb_writew(epio, MUSB_TXCSR, csr);
+                       }
+               }
+
+#elif defined(CONFIG_USB_TI_CPPI_DMA)
+               /* program endpoint CSR first, then setup DMA */
+               csr &= ~(MUSB_TXCSR_AUTOSET
+                               | MUSB_TXCSR_DMAMODE
+                               | MUSB_TXCSR_P_UNDERRUN
+                               | MUSB_TXCSR_TXPKTRDY);
+               csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB;
+               musb_writew(epio, MUSB_TXCSR,
+                       (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
+                               | csr);
+
+               /* ensure writebuffer is empty */
+               csr = musb_readw(epio, MUSB_TXCSR);
+
+               /* NOTE host side sets DMAENAB later than this; both are
+                * OK since the transfer dma glue (between CPPI and Mentor
+                * fifos) just tells CPPI it could start.  Data only moves
+                * to the USB TX fifo when both fifos are ready.
+                */
+
+               /* "mode" is irrelevant here; handle terminating ZLPs like
+                * PIO does, since the hardware RNDIS mode seems unreliable
+                * except for the last-packet-is-already-short case.
+                */
+               use_dma = use_dma && c->channel_program(
+                               musb_ep->dma, musb_ep->packet_sz,
+                               0,
+                               request->dma,
+                               request->length);
+               if (!use_dma) {
+                       c->channel_release(musb_ep->dma);
+                       musb_ep->dma = NULL;
+                       /* ASSERT: DMAENAB clear */
+                       csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
+                       /* invariant: prequest->buf is non-null */
+               }
+#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
+               use_dma = use_dma && c->channel_program(
+                               musb_ep->dma, musb_ep->packet_sz,
+                               request->zero,
+                               request->dma,
+                               request->length);
+#endif
+       }
+#endif
+
+       if (!use_dma) {
+               musb_write_fifo(musb_ep->hw_ep, fifo_count,
+                               (u8 *) (request->buf + request->actual));
+               request->actual += fifo_count;
+               csr |= MUSB_TXCSR_TXPKTRDY;
+               csr &= ~MUSB_TXCSR_P_UNDERRUN;
+               musb_writew(epio, MUSB_TXCSR, csr);
+       }
+
+       /* host may already have the data when this message shows... */
+       DBG(3, "%s TX/IN %s len %d/%d, txcsr %04x, fifo %d/%d\n",
+                       musb_ep->end_point.name, use_dma ? "dma" : "pio",
+                       request->actual, request->length,
+                       musb_readw(epio, MUSB_TXCSR),
+                       fifo_count,
+                       musb_readw(epio, MUSB_TXMAXP));
+}
+
+/*
+ * FIFO state update (e.g. data ready).
+ * Called from IRQ,  with controller locked.
+ */
+void musb_g_tx(struct musb *musb, u8 epnum)
+{
+       u16                     csr;
+       struct usb_request      *request;
+       u8 __iomem              *mbase = musb->mregs;
+       struct musb_ep          *musb_ep = &musb->endpoints[epnum].ep_in;
+       void __iomem            *epio = musb->endpoints[epnum].regs;
+       struct dma_channel      *dma;
+
+       musb_ep_select(mbase, epnum);
+       request = next_request(musb_ep);
+
+       csr = musb_readw(epio, MUSB_TXCSR);
+       DBG(4, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr);
+
+       dma = is_dma_capable() ? musb_ep->dma : NULL;
+       do {
+               /* REVISIT for high bandwidth, MUSB_TXCSR_P_INCOMPTX
+                * probably rates reporting as a host error
+                */
+               if (csr & MUSB_TXCSR_P_SENTSTALL) {
+                       csr |= MUSB_TXCSR_P_WZC_BITS;
+                       csr &= ~MUSB_TXCSR_P_SENTSTALL;
+                       musb_writew(epio, MUSB_TXCSR, csr);
+                       if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+                               dma->status = MUSB_DMA_STATUS_CORE_ABORT;
+                               musb->dma_controller->channel_abort(dma);
+                       }
+
+                       if (request)
+                               musb_g_giveback(musb_ep, request, -EPIPE);
+
+                       break;
+               }
+
+               if (csr & MUSB_TXCSR_P_UNDERRUN) {
+                       /* we NAKed, no big deal ... little reason to care */
+                       csr |= MUSB_TXCSR_P_WZC_BITS;
+                       csr &= ~(MUSB_TXCSR_P_UNDERRUN
+                                       | MUSB_TXCSR_TXPKTRDY);
+                       musb_writew(epio, MUSB_TXCSR, csr);
+                       DBG(20, "underrun on ep%d, req %p\n", epnum, request);
+               }
+
+               if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+                       /* SHOULD NOT HAPPEN ... has with cppi though, after
+                        * changing SENDSTALL (and other cases); harmless?
+                        */
+                       DBG(5, "%s dma still busy?\n", musb_ep->end_point.name);
+                       break;
+               }
+
+               if (request) {
+                       u8      is_dma = 0;
+
+                       if (dma && (csr & MUSB_TXCSR_DMAENAB)) {
+                               is_dma = 1;
+                               csr |= MUSB_TXCSR_P_WZC_BITS;
+                               csr &= ~(MUSB_TXCSR_DMAENAB
+                                               | MUSB_TXCSR_P_UNDERRUN
+                                               | MUSB_TXCSR_TXPKTRDY);
+                               musb_writew(epio, MUSB_TXCSR, csr);
+                               /* ensure writebuffer is empty */
+                               csr = musb_readw(epio, MUSB_TXCSR);
+                               request->actual += musb_ep->dma->actual_len;
+                               DBG(4, "TXCSR%d %04x, dma off, "
+                                               "len %zu, req %p\n",
+                                       epnum, csr,
+                                       musb_ep->dma->actual_len,
+                                       request);
+                       }
+
+                       if (is_dma || request->actual == request->length) {
+
+                               /* First, maybe a terminating short packet.
+                                * Some DMA engines might handle this by
+                                * themselves.
+                                */
+                               if ((request->zero
+                                               && request->length
+                                               && (request->length
+                                                       % musb_ep->packet_sz)
+                                                       == 0)
+#ifdef CONFIG_USB_INVENTRA_DMA
+                                       || (is_dma &&
+                                               ((!dma->desired_mode) ||
+                                                   (request->actual &
+                                                   (musb_ep->packet_sz - 1))))
+#endif
+                               ) {
+                                       /* on dma completion, fifo may not
+                                        * be available yet ...
+                                        */
+                                       if (csr & MUSB_TXCSR_TXPKTRDY)
+                                               break;
+
+                                       DBG(4, "sending zero pkt\n");
+                                       musb_writew(epio, MUSB_TXCSR,
+                                                       MUSB_TXCSR_MODE
+                                                       | MUSB_TXCSR_TXPKTRDY);
+                                       request->zero = 0;
+                               }
+
+                               /* ... or if not, then complete it */
+                               musb_g_giveback(musb_ep, request, 0);
+
+                               /* kickstart next transfer if appropriate;
+                                * the packet that just completed might not
+                                * be transmitted for hours or days.
+                                * REVISIT for double buffering...
+                                * FIXME revisit for stalls too...
+                                */
+                               musb_ep_select(mbase, epnum);
+                               csr = musb_readw(epio, MUSB_TXCSR);
+                               if (csr & MUSB_TXCSR_FIFONOTEMPTY)
+                                       break;
+                               request = musb_ep->desc
+                                               ? next_request(musb_ep)
+                                               : NULL;
+                               if (!request) {
+                                       DBG(4, "%s idle now\n",
+                                               musb_ep->end_point.name);
+                                       break;
+                               }
+                       }
+
+                       txstate(musb, to_musb_request(request));
+               }
+
+       } while (0);
+}
+
+/* ------------------------------------------------------------ */
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+
+/* Peripheral rx (OUT) using Mentor DMA works as follows:
+       - Only mode 0 is used.
+
+       - Request is queued by the gadget class driver.
+               -> if queue was previously empty, rxstate()
+
+       - Host sends OUT token which causes an endpoint interrupt
+         /\      -> RxReady
+         |           -> if request queued, call rxstate
+         |             /\      -> setup DMA
+         |             |            -> DMA interrupt on completion
+         |             |               -> RxReady
+         |             |                     -> stop DMA
+         |             |                     -> ack the read
+         |             |                     -> if data recd = max expected
+         |             |                               by the request, or host
+         |             |                               sent a short packet,
+         |             |                               complete the request,
+         |             |                               and start the next one.
+         |             |_____________________________________|
+         |                                      else just wait for the host
+         |                                         to send the next OUT token.
+         |__________________________________________________|
+
+ * Non-Mentor DMA engines can of course work differently.
+ */
+
+#endif
+
+/*
+ * Context: controller locked, IRQs blocked, endpoint selected
+ */
+static void rxstate(struct musb *musb, struct musb_request *req)
+{
+       u16                     csr = 0;
+       const u8                epnum = req->epnum;
+       struct usb_request      *request = &req->request;
+       struct musb_ep          *musb_ep = &musb->endpoints[epnum].ep_out;
+       void __iomem            *epio = musb->endpoints[epnum].regs;
+       u16                     fifo_count = 0;
+       u16                     len = musb_ep->packet_sz;
+
+       csr = musb_readw(epio, MUSB_RXCSR);
+
+       if (is_cppi_enabled() && musb_ep->dma) {
+               struct dma_controller   *c = musb->dma_controller;
+               struct dma_channel      *channel = musb_ep->dma;
+
+               /* NOTE:  CPPI won't actually stop advancing the DMA
+                * queue after short packet transfers, so this is almost
+                * always going to run as IRQ-per-packet DMA so that
+                * faults will be handled correctly.
+                */
+               if (c->channel_program(channel,
+                               musb_ep->packet_sz,
+                               !request->short_not_ok,
+                               request->dma + request->actual,
+                               request->length - request->actual)) {
+
+                       /* make sure that if an rxpkt arrived after the irq,
+                        * the cppi engine will be ready to take it as soon
+                        * as DMA is enabled
+                        */
+                       csr &= ~(MUSB_RXCSR_AUTOCLEAR
+                                       | MUSB_RXCSR_DMAMODE);
+                       csr |= MUSB_RXCSR_DMAENAB | MUSB_RXCSR_P_WZC_BITS;
+                       musb_writew(epio, MUSB_RXCSR, csr);
+                       return;
+               }
+       }
+
+       if (csr & MUSB_RXCSR_RXPKTRDY) {
+               len = musb_readw(epio, MUSB_RXCOUNT);
+               if (request->actual < request->length) {
+#ifdef CONFIG_USB_INVENTRA_DMA
+                       if (is_dma_capable() && musb_ep->dma) {
+                               struct dma_controller   *c;
+                               struct dma_channel      *channel;
+                               int                     use_dma = 0;
+
+                               c = musb->dma_controller;
+                               channel = musb_ep->dma;
+
+       /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in
+        * mode 0 only. So we do not get endpoint interrupts due to DMA
+        * completion. We only get interrupts from DMA controller.
+        *
+        * We could operate in DMA mode 1 if we knew the size of the tranfer
+        * in advance. For mass storage class, request->length = what the host
+        * sends, so that'd work.  But for pretty much everything else,
+        * request->length is routinely more than what the host sends. For
+        * most these gadgets, end of is signified either by a short packet,
+        * or filling the last byte of the buffer.  (Sending extra data in
+        * that last pckate should trigger an overflow fault.)  But in mode 1,
+        * we don't get DMA completion interrrupt for short packets.
+        *
+        * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1),
+        * to get endpoint interrupt on every DMA req, but that didn't seem
+        * to work reliably.
+        *
+        * REVISIT an updated g_file_storage can set req->short_not_ok, which
+        * then becomes usable as a runtime "use mode 1" hint...
+        */
+
+                               csr |= MUSB_RXCSR_DMAENAB;
+#ifdef USE_MODE1
+                               csr |= MUSB_RXCSR_AUTOCLEAR;
+                               /* csr |= MUSB_RXCSR_DMAMODE; */
+
+                               /* this special sequence (enabling and then
+                                * disabling MUSB_RXCSR_DMAMODE) is required
+                                * to get DMAReq to activate
+                                */
+                               musb_writew(epio, MUSB_RXCSR,
+                                       csr | MUSB_RXCSR_DMAMODE);
+#endif
+                               musb_writew(epio, MUSB_RXCSR, csr);
+
+                               if (request->actual < request->length) {
+                                       int transfer_size = 0;
+#ifdef USE_MODE1
+                                       transfer_size = min(request->length,
+                                                       channel->max_len);
+#else
+                                       transfer_size = len;
+#endif
+                                       if (transfer_size <= musb_ep->packet_sz)
+                                               musb_ep->dma->desired_mode = 0;
+                                       else
+                                               musb_ep->dma->desired_mode = 1;
+
+                                       use_dma = c->channel_program(
+                                                       channel,
+                                                       musb_ep->packet_sz,
+                                                       channel->desired_mode,
+                                                       request->dma
+                                                       + request->actual,
+                                                       transfer_size);
+                               }
+
+                               if (use_dma)
+                                       return;
+                       }
+#endif /* Mentor's DMA */
+
+                       fifo_count = request->length - request->actual;
+                       DBG(3, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n",
+                                       musb_ep->end_point.name,
+                                       len, fifo_count,
+                                       musb_ep->packet_sz);
+
+                       fifo_count = min(len, fifo_count);
+
+#ifdef CONFIG_USB_TUSB_OMAP_DMA
+                       if (tusb_dma_omap() && musb_ep->dma) {
+                               struct dma_controller *c = musb->dma_controller;
+                               struct dma_channel *channel = musb_ep->dma;
+                               u32 dma_addr = request->dma + request->actual;
+                               int ret;
+
+                               ret = c->channel_program(channel,
+                                               musb_ep->packet_sz,
+                                               channel->desired_mode,
+                                               dma_addr,
+                                               fifo_count);
+                               if (ret)
+                                       return;
+                       }
+#endif
+
+                       musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *)
+                                       (request->buf + request->actual));
+                       request->actual += fifo_count;
+
+                       /* REVISIT if we left anything in the fifo, flush
+                        * it and report -EOVERFLOW
+                        */
+
+                       /* ack the read! */
+                       csr |= MUSB_RXCSR_P_WZC_BITS;
+                       csr &= ~MUSB_RXCSR_RXPKTRDY;
+                       musb_writew(epio, MUSB_RXCSR, csr);
+               }
+       }
+
+       /* reach the end or short packet detected */
+       if (request->actual == request->length || len < musb_ep->packet_sz)
+               musb_g_giveback(musb_ep, request, 0);
+}
+
+/*
+ * Data ready for a request; called from IRQ
+ */
+void musb_g_rx(struct musb *musb, u8 epnum)
+{
+       u16                     csr;
+       struct usb_request      *request;
+       void __iomem            *mbase = musb->mregs;
+       struct musb_ep          *musb_ep = &musb->endpoints[epnum].ep_out;
+       void __iomem            *epio = musb->endpoints[epnum].regs;
+       struct dma_channel      *dma;
+
+       musb_ep_select(mbase, epnum);
+
+       request = next_request(musb_ep);
+
+       csr = musb_readw(epio, MUSB_RXCSR);
+       dma = is_dma_capable() ? musb_ep->dma : NULL;
+
+       DBG(4, "<== %s, rxcsr %04x%s %p\n", musb_ep->end_point.name,
+                       csr, dma ? " (dma)" : "", request);
+
+       if (csr & MUSB_RXCSR_P_SENTSTALL) {
+               if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+                       dma->status = MUSB_DMA_STATUS_CORE_ABORT;
+                       (void) musb->dma_controller->channel_abort(dma);
+                       request->actual += musb_ep->dma->actual_len;
+               }
+
+               csr |= MUSB_RXCSR_P_WZC_BITS;
+               csr &= ~MUSB_RXCSR_P_SENTSTALL;
+               musb_writew(epio, MUSB_RXCSR, csr);
+
+               if (request)
+                       musb_g_giveback(musb_ep, request, -EPIPE);
+               goto done;
+       }
+
+       if (csr & MUSB_RXCSR_P_OVERRUN) {
+               /* csr |= MUSB_RXCSR_P_WZC_BITS; */
+               csr &= ~MUSB_RXCSR_P_OVERRUN;
+               musb_writew(epio, MUSB_RXCSR, csr);
+
+               DBG(3, "%s iso overrun on %p\n", musb_ep->name, request);
+               if (request && request->status == -EINPROGRESS)
+                       request->status = -EOVERFLOW;
+       }
+       if (csr & MUSB_RXCSR_INCOMPRX) {
+               /* REVISIT not necessarily an error */
+               DBG(4, "%s, incomprx\n", musb_ep->end_point.name);
+       }
+
+       if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+               /* "should not happen"; likely RXPKTRDY pending for DMA */
+               DBG((csr & MUSB_RXCSR_DMAENAB) ? 4 : 1,
+                       "%s busy, csr %04x\n",
+                       musb_ep->end_point.name, csr);
+               goto done;
+       }
+
+       if (dma && (csr & MUSB_RXCSR_DMAENAB)) {
+               csr &= ~(MUSB_RXCSR_AUTOCLEAR
+                               | MUSB_RXCSR_DMAENAB
+                               | MUSB_RXCSR_DMAMODE);
+               musb_writew(epio, MUSB_RXCSR,
+                       MUSB_RXCSR_P_WZC_BITS | csr);
+
+               request->actual += musb_ep->dma->actual_len;
+
+               DBG(4, "RXCSR%d %04x, dma off, %04x, len %zu, req %p\n",
+                       epnum, csr,
+                       musb_readw(epio, MUSB_RXCSR),
+                       musb_ep->dma->actual_len, request);
+
+#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA)
+               /* Autoclear doesn't clear RxPktRdy for short packets */
+               if ((dma->desired_mode == 0)
+                               || (dma->actual_len
+                                       & (musb_ep->packet_sz - 1))) {
+                       /* ack the read! */
+                       csr &= ~MUSB_RXCSR_RXPKTRDY;
+                       musb_writew(epio, MUSB_RXCSR, csr);
+               }
+
+               /* incomplete, and not short? wait for next IN packet */
+               if ((request->actual < request->length)
+                               && (musb_ep->dma->actual_len
+                                       == musb_ep->packet_sz))
+                       goto done;
+#endif
+               musb_g_giveback(musb_ep, request, 0);
+
+               request = next_request(musb_ep);
+               if (!request)
+                       goto done;
+
+               /* don't start more i/o till the stall clears */
+               musb_ep_select(mbase, epnum);
+               csr = musb_readw(epio, MUSB_RXCSR);
+               if (csr & MUSB_RXCSR_P_SENDSTALL)
+                       goto done;
+       }
+
+
+       /* analyze request if the ep is hot */
+       if (request)
+               rxstate(musb, to_musb_request(request));
+       else
+               DBG(3, "packet waiting for %s%s request\n",
+                               musb_ep->desc ? "" : "inactive ",
+                               musb_ep->end_point.name);
+
+done:
+       return;
+}
+
+/* ------------------------------------------------------------ */
+
+static int musb_gadget_enable(struct usb_ep *ep,
+                       const struct usb_endpoint_descriptor *desc)
+{
+       unsigned long           flags;
+       struct musb_ep          *musb_ep;
+       struct musb_hw_ep       *hw_ep;
+       void __iomem            *regs;
+       struct musb             *musb;
+       void __iomem    *mbase;
+       u8              epnum;
+       u16             csr;
+       unsigned        tmp;
+       int             status = -EINVAL;
+
+       if (!ep || !desc)
+               return -EINVAL;
+
+       musb_ep = to_musb_ep(ep);
+       hw_ep = musb_ep->hw_ep;
+       regs = hw_ep->regs;
+       musb = musb_ep->musb;
+       mbase = musb->mregs;
+       epnum = musb_ep->current_epnum;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       if (musb_ep->desc) {
+               status = -EBUSY;
+               goto fail;
+       }
+       musb_ep->type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+
+       /* check direction and (later) maxpacket size against endpoint */
+       if ((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) != epnum)
+               goto fail;
+
+       /* REVISIT this rules out high bandwidth periodic transfers */
+       tmp = le16_to_cpu(desc->wMaxPacketSize);
+       if (tmp & ~0x07ff)
+               goto fail;
+       musb_ep->packet_sz = tmp;
+
+       /* enable the interrupts for the endpoint, set the endpoint
+        * packet size (or fail), set the mode, clear the fifo
+        */
+       musb_ep_select(mbase, epnum);
+       if (desc->bEndpointAddress & USB_DIR_IN) {
+               u16 int_txe = musb_readw(mbase, MUSB_INTRTXE);
+
+               if (hw_ep->is_shared_fifo)
+                       musb_ep->is_in = 1;
+               if (!musb_ep->is_in)
+                       goto fail;
+               if (tmp > hw_ep->max_packet_sz_tx)
+                       goto fail;
+
+               int_txe |= (1 << epnum);
+               musb_writew(mbase, MUSB_INTRTXE, int_txe);
+
+               /* REVISIT if can_bulk_split(), use by updating "tmp";
+                * likewise high bandwidth periodic tx
+                */
+               musb_writew(regs, MUSB_TXMAXP, tmp);
+
+               csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG;
+               if (musb_readw(regs, MUSB_TXCSR)
+                               & MUSB_TXCSR_FIFONOTEMPTY)
+                       csr |= MUSB_TXCSR_FLUSHFIFO;
+               if (musb_ep->type == USB_ENDPOINT_XFER_ISOC)
+                       csr |= MUSB_TXCSR_P_ISO;
+
+               /* set twice in case of double buffering */
+               musb_writew(regs, MUSB_TXCSR, csr);
+               /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */
+               musb_writew(regs, MUSB_TXCSR, csr);
+
+       } else {
+               u16 int_rxe = musb_readw(mbase, MUSB_INTRRXE);
+
+               if (hw_ep->is_shared_fifo)
+                       musb_ep->is_in = 0;
+               if (musb_ep->is_in)
+                       goto fail;
+               if (tmp > hw_ep->max_packet_sz_rx)
+                       goto fail;
+
+               int_rxe |= (1 << epnum);
+               musb_writew(mbase, MUSB_INTRRXE, int_rxe);
+
+               /* REVISIT if can_bulk_combine() use by updating "tmp"
+                * likewise high bandwidth periodic rx
+                */
+               musb_writew(regs, MUSB_RXMAXP, tmp);
+
+               /* force shared fifo to OUT-only mode */
+               if (hw_ep->is_shared_fifo) {
+                       csr = musb_readw(regs, MUSB_TXCSR);
+                       csr &= ~(MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY);
+                       musb_writew(regs, MUSB_TXCSR, csr);
+               }
+
+               csr = MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_CLRDATATOG;
+               if (musb_ep->type == USB_ENDPOINT_XFER_ISOC)
+                       csr |= MUSB_RXCSR_P_ISO;
+               else if (musb_ep->type == USB_ENDPOINT_XFER_INT)
+                       csr |= MUSB_RXCSR_DISNYET;
+
+               /* set twice in case of double buffering */
+               musb_writew(regs, MUSB_RXCSR, csr);
+               musb_writew(regs, MUSB_RXCSR, csr);
+       }
+
+       /* NOTE:  all the I/O code _should_ work fine without DMA, in case
+        * for some reason you run out of channels here.
+        */
+       if (is_dma_capable() && musb->dma_controller) {
+               struct dma_controller   *c = musb->dma_controller;
+
+               musb_ep->dma = c->channel_alloc(c, hw_ep,
+                               (desc->bEndpointAddress & USB_DIR_IN));
+       } else
+               musb_ep->dma = NULL;
+
+       musb_ep->desc = desc;
+       musb_ep->busy = 0;
+       status = 0;
+
+       pr_debug("%s periph: enabled %s for %s %s, %smaxpacket %d\n",
+                       musb_driver_name, musb_ep->end_point.name,
+                       ({ char *s; switch (musb_ep->type) {
+                       case USB_ENDPOINT_XFER_BULK:    s = "bulk"; break;
+                       case USB_ENDPOINT_XFER_INT:     s = "int"; break;
+                       default:                        s = "iso"; break;
+                       }; s; }),
+                       musb_ep->is_in ? "IN" : "OUT",
+                       musb_ep->dma ? "dma, " : "",
+                       musb_ep->packet_sz);
+
+       schedule_work(&musb->irq_work);
+
+fail:
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return status;
+}
+
+/*
+ * Disable an endpoint flushing all requests queued.
+ */
+static int musb_gadget_disable(struct usb_ep *ep)
+{
+       unsigned long   flags;
+       struct musb     *musb;
+       u8              epnum;
+       struct musb_ep  *musb_ep;
+       void __iomem    *epio;
+       int             status = 0;
+
+       musb_ep = to_musb_ep(ep);
+       musb = musb_ep->musb;
+       epnum = musb_ep->current_epnum;
+       epio = musb->endpoints[epnum].regs;
+
+       spin_lock_irqsave(&musb->lock, flags);
+       musb_ep_select(musb->mregs, epnum);
+
+       /* zero the endpoint sizes */
+       if (musb_ep->is_in) {
+               u16 int_txe = musb_readw(musb->mregs, MUSB_INTRTXE);
+               int_txe &= ~(1 << epnum);
+               musb_writew(musb->mregs, MUSB_INTRTXE, int_txe);
+               musb_writew(epio, MUSB_TXMAXP, 0);
+       } else {
+               u16 int_rxe = musb_readw(musb->mregs, MUSB_INTRRXE);
+               int_rxe &= ~(1 << epnum);
+               musb_writew(musb->mregs, MUSB_INTRRXE, int_rxe);
+               musb_writew(epio, MUSB_RXMAXP, 0);
+       }
+
+       musb_ep->desc = NULL;
+
+       /* abort all pending DMA and requests */
+       nuke(musb_ep, -ESHUTDOWN);
+
+       schedule_work(&musb->irq_work);
+
+       spin_unlock_irqrestore(&(musb->lock), flags);
+
+       DBG(2, "%s\n", musb_ep->end_point.name);
+
+       return status;
+}
+
+/*
+ * Allocate a request for an endpoint.
+ * Reused by ep0 code.
+ */
+struct usb_request *musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
+{
+       struct musb_ep          *musb_ep = to_musb_ep(ep);
+       struct musb_request     *request = NULL;
+
+       request = kzalloc(sizeof *request, gfp_flags);
+       if (request) {
+               INIT_LIST_HEAD(&request->request.list);
+               request->request.dma = DMA_ADDR_INVALID;
+               request->epnum = musb_ep->current_epnum;
+               request->ep = musb_ep;
+       }
+
+       return &request->request;
+}
+
+/*
+ * Free a request
+ * Reused by ep0 code.
+ */
+void musb_free_request(struct usb_ep *ep, struct usb_request *req)
+{
+       kfree(to_musb_request(req));
+}
+
+static LIST_HEAD(buffers);
+
+struct free_record {
+       struct list_head        list;
+       struct device           *dev;
+       unsigned                bytes;
+       dma_addr_t              dma;
+};
+
+/*
+ * Context: controller locked, IRQs blocked.
+ */
+static void musb_ep_restart(struct musb *musb, struct musb_request *req)
+{
+       DBG(3, "<== %s request %p len %u on hw_ep%d\n",
+               req->tx ? "TX/IN" : "RX/OUT",
+               &req->request, req->request.length, req->epnum);
+
+       musb_ep_select(musb->mregs, req->epnum);
+       if (req->tx)
+               txstate(musb, req);
+       else
+               rxstate(musb, req);
+}
+
+static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
+                       gfp_t gfp_flags)
+{
+       struct musb_ep          *musb_ep;
+       struct musb_request     *request;
+       struct musb             *musb;
+       int                     status = 0;
+       unsigned long           lockflags;
+
+       if (!ep || !req)
+               return -EINVAL;
+       if (!req->buf)
+               return -ENODATA;
+
+       musb_ep = to_musb_ep(ep);
+       musb = musb_ep->musb;
+
+       request = to_musb_request(req);
+       request->musb = musb;
+
+       if (request->ep != musb_ep)
+               return -EINVAL;
+
+       DBG(4, "<== to %s request=%p\n", ep->name, req);
+
+       /* request is mine now... */
+       request->request.actual = 0;
+       request->request.status = -EINPROGRESS;
+       request->epnum = musb_ep->current_epnum;
+       request->tx = musb_ep->is_in;
+
+       if (is_dma_capable() && musb_ep->dma) {
+               if (request->request.dma == DMA_ADDR_INVALID) {
+                       request->request.dma = dma_map_single(
+                                       musb->controller,
+                                       request->request.buf,
+                                       request->request.length,
+                                       request->tx
+                                               ? DMA_TO_DEVICE
+                                               : DMA_FROM_DEVICE);
+                       request->mapped = 1;
+               } else {
+                       dma_sync_single_for_device(musb->controller,
+                                       request->request.dma,
+                                       request->request.length,
+                                       request->tx
+                                               ? DMA_TO_DEVICE
+                                               : DMA_FROM_DEVICE);
+                       request->mapped = 0;
+               }
+       } else if (!req->buf) {
+               return -ENODATA;
+       } else
+               request->mapped = 0;
+
+       spin_lock_irqsave(&musb->lock, lockflags);
+
+       /* don't queue if the ep is down */
+       if (!musb_ep->desc) {
+               DBG(4, "req %p queued to %s while ep %s\n",
+                               req, ep->name, "disabled");
+               status = -ESHUTDOWN;
+               goto cleanup;
+       }
+
+       /* add request to the list */
+       list_add_tail(&(request->request.list), &(musb_ep->req_list));
+
+       /* it this is the head of the queue, start i/o ... */
+       if (!musb_ep->busy && &request->request.list == musb_ep->req_list.next)
+               musb_ep_restart(musb, request);
+
+cleanup:
+       spin_unlock_irqrestore(&musb->lock, lockflags);
+       return status;
+}
+
+static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request)
+{
+       struct musb_ep          *musb_ep = to_musb_ep(ep);
+       struct usb_request      *r;
+       unsigned long           flags;
+       int                     status = 0;
+       struct musb             *musb = musb_ep->musb;
+
+       if (!ep || !request || to_musb_request(request)->ep != musb_ep)
+               return -EINVAL;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       list_for_each_entry(r, &musb_ep->req_list, list) {
+               if (r == request)
+                       break;
+       }
+       if (r != request) {
+               DBG(3, "request %p not queued to %s\n", request, ep->name);
+               status = -EINVAL;
+               goto done;
+       }
+
+       /* if the hardware doesn't have the request, easy ... */
+       if (musb_ep->req_list.next != &request->list || musb_ep->busy)
+               musb_g_giveback(musb_ep, request, -ECONNRESET);
+
+       /* ... else abort the dma transfer ... */
+       else if (is_dma_capable() && musb_ep->dma) {
+               struct dma_controller   *c = musb->dma_controller;
+
+               musb_ep_select(musb->mregs, musb_ep->current_epnum);
+               if (c->channel_abort)
+                       status = c->channel_abort(musb_ep->dma);
+               else
+                       status = -EBUSY;
+               if (status == 0)
+                       musb_g_giveback(musb_ep, request, -ECONNRESET);
+       } else {
+               /* NOTE: by sticking to easily tested hardware/driver states,
+                * we leave counting of in-flight packets imprecise.
+                */
+               musb_g_giveback(musb_ep, request, -ECONNRESET);
+       }
+
+done:
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return status;
+}
+
+/*
+ * Set or clear the halt bit of an endpoint. A halted enpoint won't tx/rx any
+ * data but will queue requests.
+ *
+ * exported to ep0 code
+ */
+int musb_gadget_set_halt(struct usb_ep *ep, int value)
+{
+       struct musb_ep          *musb_ep = to_musb_ep(ep);
+       u8                      epnum = musb_ep->current_epnum;
+       struct musb             *musb = musb_ep->musb;
+       void __iomem            *epio = musb->endpoints[epnum].regs;
+       void __iomem            *mbase;
+       unsigned long           flags;
+       u16                     csr;
+       struct musb_request     *request = NULL;
+       int                     status = 0;
+
+       if (!ep)
+               return -EINVAL;
+       mbase = musb->mregs;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       if ((USB_ENDPOINT_XFER_ISOC == musb_ep->type)) {
+               status = -EINVAL;
+               goto done;
+       }
+
+       musb_ep_select(mbase, epnum);
+
+       /* cannot portably stall with non-empty FIFO */
+       request = to_musb_request(next_request(musb_ep));
+       if (value && musb_ep->is_in) {
+               csr = musb_readw(epio, MUSB_TXCSR);
+               if (csr & MUSB_TXCSR_FIFONOTEMPTY) {
+                       DBG(3, "%s fifo busy, cannot halt\n", ep->name);
+                       spin_unlock_irqrestore(&musb->lock, flags);
+                       return -EAGAIN;
+               }
+
+       }
+
+       /* set/clear the stall and toggle bits */
+       DBG(2, "%s: %s stall\n", ep->name, value ? "set" : "clear");
+       if (musb_ep->is_in) {
+               csr = musb_readw(epio, MUSB_TXCSR);
+               if (csr & MUSB_TXCSR_FIFONOTEMPTY)
+                       csr |= MUSB_TXCSR_FLUSHFIFO;
+               csr |= MUSB_TXCSR_P_WZC_BITS
+                       | MUSB_TXCSR_CLRDATATOG;
+               if (value)
+                       csr |= MUSB_TXCSR_P_SENDSTALL;
+               else
+                       csr &= ~(MUSB_TXCSR_P_SENDSTALL
+                               | MUSB_TXCSR_P_SENTSTALL);
+               csr &= ~MUSB_TXCSR_TXPKTRDY;
+               musb_writew(epio, MUSB_TXCSR, csr);
+       } else {
+               csr = musb_readw(epio, MUSB_RXCSR);
+               csr |= MUSB_RXCSR_P_WZC_BITS
+                       | MUSB_RXCSR_FLUSHFIFO
+                       | MUSB_RXCSR_CLRDATATOG;
+               if (value)
+                       csr |= MUSB_RXCSR_P_SENDSTALL;
+               else
+                       csr &= ~(MUSB_RXCSR_P_SENDSTALL
+                               | MUSB_RXCSR_P_SENTSTALL);
+               musb_writew(epio, MUSB_RXCSR, csr);
+       }
+
+done:
+
+       /* maybe start the first request in the queue */
+       if (!musb_ep->busy && !value && request) {
+               DBG(3, "restarting the request\n");
+               musb_ep_restart(musb, request);
+       }
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return status;
+}
+
+static int musb_gadget_fifo_status(struct usb_ep *ep)
+{
+       struct musb_ep          *musb_ep = to_musb_ep(ep);
+       void __iomem            *epio = musb_ep->hw_ep->regs;
+       int                     retval = -EINVAL;
+
+       if (musb_ep->desc && !musb_ep->is_in) {
+               struct musb             *musb = musb_ep->musb;
+               int                     epnum = musb_ep->current_epnum;
+               void __iomem            *mbase = musb->mregs;
+               unsigned long           flags;
+
+               spin_lock_irqsave(&musb->lock, flags);
+
+               musb_ep_select(mbase, epnum);
+               /* FIXME return zero unless RXPKTRDY is set */
+               retval = musb_readw(epio, MUSB_RXCOUNT);
+
+               spin_unlock_irqrestore(&musb->lock, flags);
+       }
+       return retval;
+}
+
+static void musb_gadget_fifo_flush(struct usb_ep *ep)
+{
+       struct musb_ep  *musb_ep = to_musb_ep(ep);
+       struct musb     *musb = musb_ep->musb;
+       u8              epnum = musb_ep->current_epnum;
+       void __iomem    *epio = musb->endpoints[epnum].regs;
+       void __iomem    *mbase;
+       unsigned long   flags;
+       u16             csr, int_txe;
+
+       mbase = musb->mregs;
+
+       spin_lock_irqsave(&musb->lock, flags);
+       musb_ep_select(mbase, (u8) epnum);
+
+       /* disable interrupts */
+       int_txe = musb_readw(mbase, MUSB_INTRTXE);
+       musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
+
+       if (musb_ep->is_in) {
+               csr = musb_readw(epio, MUSB_TXCSR);
+               if (csr & MUSB_TXCSR_FIFONOTEMPTY) {
+                       csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_P_WZC_BITS;
+                       musb_writew(epio, MUSB_TXCSR, csr);
+                       /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */
+                       musb_writew(epio, MUSB_TXCSR, csr);
+               }
+       } else {
+               csr = musb_readw(epio, MUSB_RXCSR);
+               csr |= MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_P_WZC_BITS;
+               musb_writew(epio, MUSB_RXCSR, csr);
+               musb_writew(epio, MUSB_RXCSR, csr);
+       }
+
+       /* re-enable interrupt */
+       musb_writew(mbase, MUSB_INTRTXE, int_txe);
+       spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static const struct usb_ep_ops musb_ep_ops = {
+       .enable         = musb_gadget_enable,
+       .disable        = musb_gadget_disable,
+       .alloc_request  = musb_alloc_request,
+       .free_request   = musb_free_request,
+       .queue          = musb_gadget_queue,
+       .dequeue        = musb_gadget_dequeue,
+       .set_halt       = musb_gadget_set_halt,
+       .fifo_status    = musb_gadget_fifo_status,
+       .fifo_flush     = musb_gadget_fifo_flush
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int musb_gadget_get_frame(struct usb_gadget *gadget)
+{
+       struct musb     *musb = gadget_to_musb(gadget);
+
+       return (int)musb_readw(musb->mregs, MUSB_FRAME);
+}
+
+static int musb_gadget_wakeup(struct usb_gadget *gadget)
+{
+       struct musb     *musb = gadget_to_musb(gadget);
+       void __iomem    *mregs = musb->mregs;
+       unsigned long   flags;
+       int             status = -EINVAL;
+       u8              power, devctl;
+       int             retries;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       switch (musb->xceiv.state) {
+       case OTG_STATE_B_PERIPHERAL:
+               /* NOTE:  OTG state machine doesn't include B_SUSPENDED;
+                * that's part of the standard usb 1.1 state machine, and
+                * doesn't affect OTG transitions.
+                */
+               if (musb->may_wakeup && musb->is_suspended)
+                       break;
+               goto done;
+       case OTG_STATE_B_IDLE:
+               /* Start SRP ... OTG not required. */
+               devctl = musb_readb(mregs, MUSB_DEVCTL);
+               DBG(2, "Sending SRP: devctl: %02x\n", devctl);
+               devctl |= MUSB_DEVCTL_SESSION;
+               musb_writeb(mregs, MUSB_DEVCTL, devctl);
+               devctl = musb_readb(mregs, MUSB_DEVCTL);
+               retries = 100;
+               while (!(devctl & MUSB_DEVCTL_SESSION)) {
+                       devctl = musb_readb(mregs, MUSB_DEVCTL);
+                       if (retries-- < 1)
+                               break;
+               }
+               retries = 10000;
+               while (devctl & MUSB_DEVCTL_SESSION) {
+                       devctl = musb_readb(mregs, MUSB_DEVCTL);
+                       if (retries-- < 1)
+                               break;
+               }
+
+               /* Block idling for at least 1s */
+               musb_platform_try_idle(musb,
+                       jiffies + msecs_to_jiffies(1 * HZ));
+
+               status = 0;
+               goto done;
+       default:
+               DBG(2, "Unhandled wake: %s\n", otg_state_string(musb));
+               goto done;
+       }
+
+       status = 0;
+
+       power = musb_readb(mregs, MUSB_POWER);
+       power |= MUSB_POWER_RESUME;
+       musb_writeb(mregs, MUSB_POWER, power);
+       DBG(2, "issue wakeup\n");
+
+       /* FIXME do this next chunk in a timer callback, no udelay */
+       mdelay(2);
+
+       power = musb_readb(mregs, MUSB_POWER);
+       power &= ~MUSB_POWER_RESUME;
+       musb_writeb(mregs, MUSB_POWER, power);
+done:
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return status;
+}
+
+static int
+musb_gadget_set_self_powered(struct usb_gadget *gadget, int is_selfpowered)
+{
+       struct musb     *musb = gadget_to_musb(gadget);
+
+       musb->is_self_powered = !!is_selfpowered;
+       return 0;
+}
+
+static void musb_pullup(struct musb *musb, int is_on)
+{
+       u8 power;
+
+       power = musb_readb(musb->mregs, MUSB_POWER);
+       if (is_on)
+               power |= MUSB_POWER_SOFTCONN;
+       else
+               power &= ~MUSB_POWER_SOFTCONN;
+
+       /* FIXME if on, HdrcStart; if off, HdrcStop */
+
+       DBG(3, "gadget %s D+ pullup %s\n",
+               musb->gadget_driver->function, is_on ? "on" : "off");
+       musb_writeb(musb->mregs, MUSB_POWER, power);
+}
+
+#if 0
+static int musb_gadget_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       DBG(2, "<= %s =>\n", __func__);
+
+       /*
+        * FIXME iff driver's softconnect flag is set (as it is during probe,
+        * though that can clear it), just musb_pullup().
+        */
+
+       return -EINVAL;
+}
+#endif
+
+static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+       struct musb     *musb = gadget_to_musb(gadget);
+
+       if (!musb->xceiv.set_power)
+               return -EOPNOTSUPP;
+       return otg_set_power(&musb->xceiv, mA);
+}
+
+static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct musb     *musb = gadget_to_musb(gadget);
+       unsigned long   flags;
+
+       is_on = !!is_on;
+
+       /* NOTE: this assumes we are sensing vbus; we'd rather
+        * not pullup unless the B-session is active.
+        */
+       spin_lock_irqsave(&musb->lock, flags);
+       if (is_on != musb->softconnect) {
+               musb->softconnect = is_on;
+               musb_pullup(musb, is_on);
+       }
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return 0;
+}
+
+static const struct usb_gadget_ops musb_gadget_operations = {
+       .get_frame              = musb_gadget_get_frame,
+       .wakeup                 = musb_gadget_wakeup,
+       .set_selfpowered        = musb_gadget_set_self_powered,
+       /* .vbus_session                = musb_gadget_vbus_session, */
+       .vbus_draw              = musb_gadget_vbus_draw,
+       .pullup                 = musb_gadget_pullup,
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* Registration */
+
+/* Only this registration code "knows" the rule (from USB standards)
+ * about there being only one external upstream port.  It assumes
+ * all peripheral ports are external...
+ */
+static struct musb *the_gadget;
+
+static void musb_gadget_release(struct device *dev)
+{
+       /* kref_put(WHAT) */
+       dev_dbg(dev, "%s\n", __func__);
+}
+
+
+static void __init
+init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
+{
+       struct musb_hw_ep       *hw_ep = musb->endpoints + epnum;
+
+       memset(ep, 0, sizeof *ep);
+
+       ep->current_epnum = epnum;
+       ep->musb = musb;
+       ep->hw_ep = hw_ep;
+       ep->is_in = is_in;
+
+       INIT_LIST_HEAD(&ep->req_list);
+
+       sprintf(ep->name, "ep%d%s", epnum,
+                       (!epnum || hw_ep->is_shared_fifo) ? "" : (
+                               is_in ? "in" : "out"));
+       ep->end_point.name = ep->name;
+       INIT_LIST_HEAD(&ep->end_point.ep_list);
+       if (!epnum) {
+               ep->end_point.maxpacket = 64;
+               ep->end_point.ops = &musb_g_ep0_ops;
+               musb->g.ep0 = &ep->end_point;
+       } else {
+               if (is_in)
+                       ep->end_point.maxpacket = hw_ep->max_packet_sz_tx;
+               else
+                       ep->end_point.maxpacket = hw_ep->max_packet_sz_rx;
+               ep->end_point.ops = &musb_ep_ops;
+               list_add_tail(&ep->end_point.ep_list, &musb->g.ep_list);
+       }
+}
+
+/*
+ * Initialize the endpoints exposed to peripheral drivers, with backlinks
+ * to the rest of the driver state.
+ */
+static inline void __init musb_g_init_endpoints(struct musb *musb)
+{
+       u8                      epnum;
+       struct musb_hw_ep       *hw_ep;
+       unsigned                count = 0;
+
+       /* intialize endpoint list just once */
+       INIT_LIST_HEAD(&(musb->g.ep_list));
+
+       for (epnum = 0, hw_ep = musb->endpoints;
+                       epnum < musb->nr_endpoints;
+                       epnum++, hw_ep++) {
+               if (hw_ep->is_shared_fifo /* || !epnum */) {
+                       init_peripheral_ep(musb, &hw_ep->ep_in, epnum, 0);
+                       count++;
+               } else {
+                       if (hw_ep->max_packet_sz_tx) {
+                               init_peripheral_ep(musb, &hw_ep->ep_in,
+                                                       epnum, 1);
+                               count++;
+                       }
+                       if (hw_ep->max_packet_sz_rx) {
+                               init_peripheral_ep(musb, &hw_ep->ep_out,
+                                                       epnum, 0);
+                               count++;
+                       }
+               }
+       }
+}
+
+/* called once during driver setup to initialize and link into
+ * the driver model; memory is zeroed.
+ */
+int __init musb_gadget_setup(struct musb *musb)
+{
+       int status;
+
+       /* REVISIT minor race:  if (erroneously) setting up two
+        * musb peripherals at the same time, only the bus lock
+        * is probably held.
+        */
+       if (the_gadget)
+               return -EBUSY;
+       the_gadget = musb;
+
+       musb->g.ops = &musb_gadget_operations;
+       musb->g.is_dualspeed = 1;
+       musb->g.speed = USB_SPEED_UNKNOWN;
+
+       /* this "gadget" abstracts/virtualizes the controller */
+       strcpy(musb->g.dev.bus_id, "gadget");
+       musb->g.dev.parent = musb->controller;
+       musb->g.dev.dma_mask = musb->controller->dma_mask;
+       musb->g.dev.release = musb_gadget_release;
+       musb->g.name = musb_driver_name;
+
+       if (is_otg_enabled(musb))
+               musb->g.is_otg = 1;
+
+       musb_g_init_endpoints(musb);
+
+       musb->is_active = 0;
+       musb_platform_try_idle(musb, 0);
+
+       status = device_register(&musb->g.dev);
+       if (status != 0)
+               the_gadget = NULL;
+       return status;
+}
+
+void musb_gadget_cleanup(struct musb *musb)
+{
+       if (musb != the_gadget)
+               return;
+
+       device_unregister(&musb->g.dev);
+       the_gadget = NULL;
+}
+
+/*
+ * Register the gadget driver. Used by gadget drivers when
+ * registering themselves with the controller.
+ *
+ * -EINVAL something went wrong (not driver)
+ * -EBUSY another gadget is already using the controller
+ * -ENOMEM no memeory to perform the operation
+ *
+ * @param driver the gadget driver
+ * @return <0 if error, 0 if everything is fine
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+       int retval;
+       unsigned long flags;
+       struct musb *musb = the_gadget;
+
+       if (!driver
+                       || driver->speed != USB_SPEED_HIGH
+                       || !driver->bind
+                       || !driver->setup)
+               return -EINVAL;
+
+       /* driver must be initialized to support peripheral mode */
+       if (!musb || !(musb->board_mode == MUSB_OTG
+                               || musb->board_mode != MUSB_OTG)) {
+               DBG(1, "%s, no dev??\n", __func__);
+               return -ENODEV;
+       }
+
+       DBG(3, "registering driver %s\n", driver->function);
+       spin_lock_irqsave(&musb->lock, flags);
+
+       if (musb->gadget_driver) {
+               DBG(1, "%s is already bound to %s\n",
+                               musb_driver_name,
+                               musb->gadget_driver->driver.name);
+               retval = -EBUSY;
+       } else {
+               musb->gadget_driver = driver;
+               musb->g.dev.driver = &driver->driver;
+               driver->driver.bus = NULL;
+               musb->softconnect = 1;
+               retval = 0;
+       }
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       if (retval == 0) {
+               retval = driver->bind(&musb->g);
+               if (retval != 0) {
+                       DBG(3, "bind to driver %s failed --> %d\n",
+                                       driver->driver.name, retval);
+                       musb->gadget_driver = NULL;
+                       musb->g.dev.driver = NULL;
+               }
+
+               spin_lock_irqsave(&musb->lock, flags);
+
+               /* REVISIT always use otg_set_peripheral(), handling
+                * issues including the root hub one below ...
+                */
+               musb->xceiv.gadget = &musb->g;
+               musb->xceiv.state = OTG_STATE_B_IDLE;
+               musb->is_active = 1;
+
+               /* FIXME this ignores the softconnect flag.  Drivers are
+                * allowed hold the peripheral inactive until for example
+                * userspace hooks up printer hardware or DSP codecs, so
+                * hosts only see fully functional devices.
+                */
+
+               if (!is_otg_enabled(musb))
+                       musb_start(musb);
+
+               spin_unlock_irqrestore(&musb->lock, flags);
+
+               if (is_otg_enabled(musb)) {
+                       DBG(3, "OTG startup...\n");
+
+                       /* REVISIT:  funcall to other code, which also
+                        * handles power budgeting ... this way also
+                        * ensures HdrcStart is indirectly called.
+                        */
+                       retval = usb_add_hcd(musb_to_hcd(musb), -1, 0);
+                       if (retval < 0) {
+                               DBG(1, "add_hcd failed, %d\n", retval);
+                               spin_lock_irqsave(&musb->lock, flags);
+                               musb->xceiv.gadget = NULL;
+                               musb->xceiv.state = OTG_STATE_UNDEFINED;
+                               musb->gadget_driver = NULL;
+                               musb->g.dev.driver = NULL;
+                               spin_unlock_irqrestore(&musb->lock, flags);
+                       }
+               }
+       }
+
+       return retval;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
+{
+       int                     i;
+       struct musb_hw_ep       *hw_ep;
+
+       /* don't disconnect if it's not connected */
+       if (musb->g.speed == USB_SPEED_UNKNOWN)
+               driver = NULL;
+       else
+               musb->g.speed = USB_SPEED_UNKNOWN;
+
+       /* deactivate the hardware */
+       if (musb->softconnect) {
+               musb->softconnect = 0;
+               musb_pullup(musb, 0);
+       }
+       musb_stop(musb);
+
+       /* killing any outstanding requests will quiesce the driver;
+        * then report disconnect
+        */
+       if (driver) {
+               for (i = 0, hw_ep = musb->endpoints;
+                               i < musb->nr_endpoints;
+                               i++, hw_ep++) {
+                       musb_ep_select(musb->mregs, i);
+                       if (hw_ep->is_shared_fifo /* || !epnum */) {
+                               nuke(&hw_ep->ep_in, -ESHUTDOWN);
+                       } else {
+                               if (hw_ep->max_packet_sz_tx)
+                                       nuke(&hw_ep->ep_in, -ESHUTDOWN);
+                               if (hw_ep->max_packet_sz_rx)
+                                       nuke(&hw_ep->ep_out, -ESHUTDOWN);
+                       }
+               }
+
+               spin_unlock(&musb->lock);
+               driver->disconnect(&musb->g);
+               spin_lock(&musb->lock);
+       }
+}
+
+/*
+ * Unregister the gadget driver. Used by gadget drivers when
+ * unregistering themselves from the controller.
+ *
+ * @param driver the gadget driver to unregister
+ */
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+       unsigned long   flags;
+       int             retval = 0;
+       struct musb     *musb = the_gadget;
+
+       if (!driver || !driver->unbind || !musb)
+               return -EINVAL;
+
+       /* REVISIT always use otg_set_peripheral() here too;
+        * this needs to shut down the OTG engine.
+        */
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+#ifdef CONFIG_USB_MUSB_OTG
+       musb_hnp_stop(musb);
+#endif
+
+       if (musb->gadget_driver == driver) {
+
+               (void) musb_gadget_vbus_draw(&musb->g, 0);
+
+               musb->xceiv.state = OTG_STATE_UNDEFINED;
+               stop_activity(musb, driver);
+
+               DBG(3, "unregistering driver %s\n", driver->function);
+               spin_unlock_irqrestore(&musb->lock, flags);
+               driver->unbind(&musb->g);
+               spin_lock_irqsave(&musb->lock, flags);
+
+               musb->gadget_driver = NULL;
+               musb->g.dev.driver = NULL;
+
+               musb->is_active = 0;
+               musb_platform_try_idle(musb, 0);
+       } else
+               retval = -EINVAL;
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       if (is_otg_enabled(musb) && retval == 0) {
+               usb_remove_hcd(musb_to_hcd(musb));
+               /* FIXME we need to be able to register another
+                * gadget driver here and have everything work;
+                * that currently misbehaves.
+                */
+       }
+
+       return retval;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+
+/* ----------------------------------------------------------------------- */
+
+/* lifecycle operations called through plat_uds.c */
+
+void musb_g_resume(struct musb *musb)
+{
+       musb->is_suspended = 0;
+       switch (musb->xceiv.state) {
+       case OTG_STATE_B_IDLE:
+               break;
+       case OTG_STATE_B_WAIT_ACON:
+       case OTG_STATE_B_PERIPHERAL:
+               musb->is_active = 1;
+               if (musb->gadget_driver && musb->gadget_driver->resume) {
+                       spin_unlock(&musb->lock);
+                       musb->gadget_driver->resume(&musb->g);
+                       spin_lock(&musb->lock);
+               }
+               break;
+       default:
+               WARNING("unhandled RESUME transition (%s)\n",
+                               otg_state_string(musb));
+       }
+}
+
+/* called when SOF packets stop for 3+ msec */
+void musb_g_suspend(struct musb *musb)
+{
+       u8      devctl;
+
+       devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+       DBG(3, "devctl %02x\n", devctl);
+
+       switch (musb->xceiv.state) {
+       case OTG_STATE_B_IDLE:
+               if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+                       musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+               break;
+       case OTG_STATE_B_PERIPHERAL:
+               musb->is_suspended = 1;
+               if (musb->gadget_driver && musb->gadget_driver->suspend) {
+                       spin_unlock(&musb->lock);
+                       musb->gadget_driver->suspend(&musb->g);
+                       spin_lock(&musb->lock);
+               }
+               break;
+       default:
+               /* REVISIT if B_HOST, clear DEVCTL.HOSTREQ;
+                * A_PERIPHERAL may need care too
+                */
+               WARNING("unhandled SUSPEND transition (%s)\n",
+                               otg_state_string(musb));
+       }
+}
+
+/* Called during SRP */
+void musb_g_wakeup(struct musb *musb)
+{
+       musb_gadget_wakeup(&musb->g);
+}
+
+/* called when VBUS drops below session threshold, and in other cases */
+void musb_g_disconnect(struct musb *musb)
+{
+       void __iomem    *mregs = musb->mregs;
+       u8      devctl = musb_readb(mregs, MUSB_DEVCTL);
+
+       DBG(3, "devctl %02x\n", devctl);
+
+       /* clear HR */
+       musb_writeb(mregs, MUSB_DEVCTL, devctl & MUSB_DEVCTL_SESSION);
+
+       /* don't draw vbus until new b-default session */
+       (void) musb_gadget_vbus_draw(&musb->g, 0);
+
+       musb->g.speed = USB_SPEED_UNKNOWN;
+       if (musb->gadget_driver && musb->gadget_driver->disconnect) {
+               spin_unlock(&musb->lock);
+               musb->gadget_driver->disconnect(&musb->g);
+               spin_lock(&musb->lock);
+       }
+
+       switch (musb->xceiv.state) {
+       default:
+#ifdef CONFIG_USB_MUSB_OTG
+               DBG(2, "Unhandled disconnect %s, setting a_idle\n",
+                       otg_state_string(musb));
+               musb->xceiv.state = OTG_STATE_A_IDLE;
+               break;
+       case OTG_STATE_A_PERIPHERAL:
+               musb->xceiv.state = OTG_STATE_A_WAIT_VFALL;
+               break;
+       case OTG_STATE_B_WAIT_ACON:
+       case OTG_STATE_B_HOST:
+#endif
+       case OTG_STATE_B_PERIPHERAL:
+       case OTG_STATE_B_IDLE:
+               musb->xceiv.state = OTG_STATE_B_IDLE;
+               break;
+       case OTG_STATE_B_SRP_INIT:
+               break;
+       }
+
+       musb->is_active = 0;
+}
+
+void musb_g_reset(struct musb *musb)
+__releases(musb->lock)
+__acquires(musb->lock)
+{
+       void __iomem    *mbase = musb->mregs;
+       u8              devctl = musb_readb(mbase, MUSB_DEVCTL);
+       u8              power;
+
+       DBG(3, "<== %s addr=%x driver '%s'\n",
+                       (devctl & MUSB_DEVCTL_BDEVICE)
+                               ? "B-Device" : "A-Device",
+                       musb_readb(mbase, MUSB_FADDR),
+                       musb->gadget_driver
+                               ? musb->gadget_driver->driver.name
+                               : NULL
+                       );
+
+       /* report disconnect, if we didn't already (flushing EP state) */
+       if (musb->g.speed != USB_SPEED_UNKNOWN)
+               musb_g_disconnect(musb);
+
+       /* clear HR */
+       else if (devctl & MUSB_DEVCTL_HR)
+               musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
+
+
+       /* what speed did we negotiate? */
+       power = musb_readb(mbase, MUSB_POWER);
+       musb->g.speed = (power & MUSB_POWER_HSMODE)
+                       ? USB_SPEED_HIGH : USB_SPEED_FULL;
+
+       /* start in USB_STATE_DEFAULT */
+       musb->is_active = 1;
+       musb->is_suspended = 0;
+       MUSB_DEV_MODE(musb);
+       musb->address = 0;
+       musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+
+       musb->may_wakeup = 0;
+       musb->g.b_hnp_enable = 0;
+       musb->g.a_alt_hnp_support = 0;
+       musb->g.a_hnp_support = 0;
+
+       /* Normal reset, as B-Device;
+        * or else after HNP, as A-Device
+        */
+       if (devctl & MUSB_DEVCTL_BDEVICE) {
+               musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+               musb->g.is_a_peripheral = 0;
+       } else if (is_otg_enabled(musb)) {
+               musb->xceiv.state = OTG_STATE_A_PERIPHERAL;
+               musb->g.is_a_peripheral = 1;
+       } else
+               WARN_ON(1);
+
+       /* start with default limits on VBUS power draw */
+       (void) musb_gadget_vbus_draw(&musb->g,
+                       is_otg_enabled(musb) ? 8 : 100);
+}
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h
new file mode 100644 (file)
index 0000000..59502da
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * MUSB OTG driver peripheral defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_GADGET_H
+#define __MUSB_GADGET_H
+
+struct musb_request {
+       struct usb_request      request;
+       struct musb_ep          *ep;
+       struct musb             *musb;
+       u8 tx;                  /* endpoint direction */
+       u8 epnum;
+       u8 mapped;
+};
+
+static inline struct musb_request *to_musb_request(struct usb_request *req)
+{
+       return req ? container_of(req, struct musb_request, request) : NULL;
+}
+
+extern struct usb_request *
+musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags);
+extern void musb_free_request(struct usb_ep *ep, struct usb_request *req);
+
+
+/*
+ * struct musb_ep - peripheral side view of endpoint rx or tx side
+ */
+struct musb_ep {
+       /* stuff towards the head is basically write-once. */
+       struct usb_ep                   end_point;
+       char                            name[12];
+       struct musb_hw_ep               *hw_ep;
+       struct musb                     *musb;
+       u8                              current_epnum;
+
+       /* ... when enabled/disabled ... */
+       u8                              type;
+       u8                              is_in;
+       u16                             packet_sz;
+       const struct usb_endpoint_descriptor    *desc;
+       struct dma_channel              *dma;
+
+       /* later things are modified based on usage */
+       struct list_head                req_list;
+
+       /* true if lock must be dropped but req_list may not be advanced */
+       u8                              busy;
+};
+
+static inline struct musb_ep *to_musb_ep(struct usb_ep *ep)
+{
+       return ep ? container_of(ep, struct musb_ep, end_point) : NULL;
+}
+
+static inline struct usb_request *next_request(struct musb_ep *ep)
+{
+       struct list_head        *queue = &ep->req_list;
+
+       if (list_empty(queue))
+               return NULL;
+       return container_of(queue->next, struct usb_request, list);
+}
+
+extern void musb_g_tx(struct musb *musb, u8 epnum);
+extern void musb_g_rx(struct musb *musb, u8 epnum);
+
+extern const struct usb_ep_ops musb_g_ep0_ops;
+
+extern int musb_gadget_setup(struct musb *);
+extern void musb_gadget_cleanup(struct musb *);
+
+extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int);
+
+extern int musb_gadget_set_halt(struct usb_ep *ep, int value);
+
+#endif         /* __MUSB_GADGET_H */
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
new file mode 100644 (file)
index 0000000..48d7d3c
--- /dev/null
@@ -0,0 +1,981 @@
+/*
+ * MUSB OTG peripheral driver ep0 handling
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+
+#include "musb_core.h"
+
+/* ep0 is always musb->endpoints[0].ep_in */
+#define        next_ep0_request(musb)  next_in_request(&(musb)->endpoints[0])
+
+/*
+ * locking note:  we use only the controller lock, for simpler correctness.
+ * It's always held with IRQs blocked.
+ *
+ * It protects the ep0 request queue as well as ep0_state, not just the
+ * controller and indexed registers.  And that lock stays held unless it
+ * needs to be dropped to allow reentering this driver ... like upcalls to
+ * the gadget driver, or adjusting endpoint halt status.
+ */
+
+static char *decode_ep0stage(u8 stage)
+{
+       switch (stage) {
+       case MUSB_EP0_STAGE_SETUP:      return "idle";
+       case MUSB_EP0_STAGE_TX:         return "in";
+       case MUSB_EP0_STAGE_RX:         return "out";
+       case MUSB_EP0_STAGE_ACKWAIT:    return "wait";
+       case MUSB_EP0_STAGE_STATUSIN:   return "in/status";
+       case MUSB_EP0_STAGE_STATUSOUT:  return "out/status";
+       default:                        return "?";
+       }
+}
+
+/* handle a standard GET_STATUS request
+ * Context:  caller holds controller lock
+ */
+static int service_tx_status_request(
+       struct musb *musb,
+       const struct usb_ctrlrequest *ctrlrequest)
+{
+       void __iomem    *mbase = musb->mregs;
+       int handled = 1;
+       u8 result[2], epnum = 0;
+       const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK;
+
+       result[1] = 0;
+
+       switch (recip) {
+       case USB_RECIP_DEVICE:
+               result[0] = musb->is_self_powered << USB_DEVICE_SELF_POWERED;
+               result[0] |= musb->may_wakeup << USB_DEVICE_REMOTE_WAKEUP;
+#ifdef CONFIG_USB_MUSB_OTG
+               if (musb->g.is_otg) {
+                       result[0] |= musb->g.b_hnp_enable
+                               << USB_DEVICE_B_HNP_ENABLE;
+                       result[0] |= musb->g.a_alt_hnp_support
+                               << USB_DEVICE_A_ALT_HNP_SUPPORT;
+                       result[0] |= musb->g.a_hnp_support
+                               << USB_DEVICE_A_HNP_SUPPORT;
+               }
+#endif
+               break;
+
+       case USB_RECIP_INTERFACE:
+               result[0] = 0;
+               break;
+
+       case USB_RECIP_ENDPOINT: {
+               int             is_in;
+               struct musb_ep  *ep;
+               u16             tmp;
+               void __iomem    *regs;
+
+               epnum = (u8) ctrlrequest->wIndex;
+               if (!epnum) {
+                       result[0] = 0;
+                       break;
+               }
+
+               is_in = epnum & USB_DIR_IN;
+               if (is_in) {
+                       epnum &= 0x0f;
+                       ep = &musb->endpoints[epnum].ep_in;
+               } else {
+                       ep = &musb->endpoints[epnum].ep_out;
+               }
+               regs = musb->endpoints[epnum].regs;
+
+               if (epnum >= MUSB_C_NUM_EPS || !ep->desc) {
+                       handled = -EINVAL;
+                       break;
+               }
+
+               musb_ep_select(mbase, epnum);
+               if (is_in)
+                       tmp = musb_readw(regs, MUSB_TXCSR)
+                                               & MUSB_TXCSR_P_SENDSTALL;
+               else
+                       tmp = musb_readw(regs, MUSB_RXCSR)
+                                               & MUSB_RXCSR_P_SENDSTALL;
+               musb_ep_select(mbase, 0);
+
+               result[0] = tmp ? 1 : 0;
+               } break;
+
+       default:
+               /* class, vendor, etc ... delegate */
+               handled = 0;
+               break;
+       }
+
+       /* fill up the fifo; caller updates csr0 */
+       if (handled > 0) {
+               u16     len = le16_to_cpu(ctrlrequest->wLength);
+
+               if (len > 2)
+                       len = 2;
+               musb_write_fifo(&musb->endpoints[0], len, result);
+       }
+
+       return handled;
+}
+
+/*
+ * handle a control-IN request, the end0 buffer contains the current request
+ * that is supposed to be a standard control request. Assumes the fifo to
+ * be at least 2 bytes long.
+ *
+ * @return 0 if the request was NOT HANDLED,
+ * < 0 when error
+ * > 0 when the request is processed
+ *
+ * Context:  caller holds controller lock
+ */
+static int
+service_in_request(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest)
+{
+       int handled = 0;        /* not handled */
+
+       if ((ctrlrequest->bRequestType & USB_TYPE_MASK)
+                       == USB_TYPE_STANDARD) {
+               switch (ctrlrequest->bRequest) {
+               case USB_REQ_GET_STATUS:
+                       handled = service_tx_status_request(musb,
+                                       ctrlrequest);
+                       break;
+
+               /* case USB_REQ_SYNC_FRAME: */
+
+               default:
+                       break;
+               }
+       }
+       return handled;
+}
+
+/*
+ * Context:  caller holds controller lock
+ */
+static void musb_g_ep0_giveback(struct musb *musb, struct usb_request *req)
+{
+       musb_g_giveback(&musb->endpoints[0].ep_in, req, 0);
+       musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+}
+
+/*
+ * Tries to start B-device HNP negotiation if enabled via sysfs
+ */
+static inline void musb_try_b_hnp_enable(struct musb *musb)
+{
+       void __iomem    *mbase = musb->mregs;
+       u8              devctl;
+
+       DBG(1, "HNP: Setting HR\n");
+       devctl = musb_readb(mbase, MUSB_DEVCTL);
+       musb_writeb(mbase, MUSB_DEVCTL, devctl | MUSB_DEVCTL_HR);
+}
+
+/*
+ * Handle all control requests with no DATA stage, including standard
+ * requests such as:
+ * USB_REQ_SET_CONFIGURATION, USB_REQ_SET_INTERFACE, unrecognized
+ *     always delegated to the gadget driver
+ * USB_REQ_SET_ADDRESS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE
+ *     always handled here, except for class/vendor/... features
+ *
+ * Context:  caller holds controller lock
+ */
+static int
+service_zero_data_request(struct musb *musb,
+               struct usb_ctrlrequest *ctrlrequest)
+__releases(musb->lock)
+__acquires(musb->lock)
+{
+       int handled = -EINVAL;
+       void __iomem *mbase = musb->mregs;
+       const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK;
+
+       /* the gadget driver handles everything except what we MUST handle */
+       if ((ctrlrequest->bRequestType & USB_TYPE_MASK)
+                       == USB_TYPE_STANDARD) {
+               switch (ctrlrequest->bRequest) {
+               case USB_REQ_SET_ADDRESS:
+                       /* change it after the status stage */
+                       musb->set_address = true;
+                       musb->address = (u8) (ctrlrequest->wValue & 0x7f);
+                       handled = 1;
+                       break;
+
+               case USB_REQ_CLEAR_FEATURE:
+                       switch (recip) {
+                       case USB_RECIP_DEVICE:
+                               if (ctrlrequest->wValue
+                                               != USB_DEVICE_REMOTE_WAKEUP)
+                                       break;
+                               musb->may_wakeup = 0;
+                               handled = 1;
+                               break;
+                       case USB_RECIP_INTERFACE:
+                               break;
+                       case USB_RECIP_ENDPOINT:{
+                               const u8 num = ctrlrequest->wIndex & 0x0f;
+                               struct musb_ep *musb_ep;
+
+                               if (num == 0
+                                               || num >= MUSB_C_NUM_EPS
+                                               || ctrlrequest->wValue
+                                                       != USB_ENDPOINT_HALT)
+                                       break;
+
+                               if (ctrlrequest->wIndex & USB_DIR_IN)
+                                       musb_ep = &musb->endpoints[num].ep_in;
+                               else
+                                       musb_ep = &musb->endpoints[num].ep_out;
+                               if (!musb_ep->desc)
+                                       break;
+
+                               /* REVISIT do it directly, no locking games */
+                               spin_unlock(&musb->lock);
+                               musb_gadget_set_halt(&musb_ep->end_point, 0);
+                               spin_lock(&musb->lock);
+
+                               /* select ep0 again */
+                               musb_ep_select(mbase, 0);
+                               handled = 1;
+                               } break;
+                       default:
+                               /* class, vendor, etc ... delegate */
+                               handled = 0;
+                               break;
+                       }
+                       break;
+
+               case USB_REQ_SET_FEATURE:
+                       switch (recip) {
+                       case USB_RECIP_DEVICE:
+                               handled = 1;
+                               switch (ctrlrequest->wValue) {
+                               case USB_DEVICE_REMOTE_WAKEUP:
+                                       musb->may_wakeup = 1;
+                                       break;
+                               case USB_DEVICE_TEST_MODE:
+                                       if (musb->g.speed != USB_SPEED_HIGH)
+                                               goto stall;
+                                       if (ctrlrequest->wIndex & 0xff)
+                                               goto stall;
+
+                                       switch (ctrlrequest->wIndex >> 8) {
+                                       case 1:
+                                               pr_debug("TEST_J\n");
+                                               /* TEST_J */
+                                               musb->test_mode_nr =
+                                                       MUSB_TEST_J;
+                                               break;
+                                       case 2:
+                                               /* TEST_K */
+                                               pr_debug("TEST_K\n");
+                                               musb->test_mode_nr =
+                                                       MUSB_TEST_K;
+                                               break;
+                                       case 3:
+                                               /* TEST_SE0_NAK */
+                                               pr_debug("TEST_SE0_NAK\n");
+                                               musb->test_mode_nr =
+                                                       MUSB_TEST_SE0_NAK;
+                                               break;
+                                       case 4:
+                                               /* TEST_PACKET */
+                                               pr_debug("TEST_PACKET\n");
+                                               musb->test_mode_nr =
+                                                       MUSB_TEST_PACKET;
+                                               break;
+                                       default:
+                                               goto stall;
+                                       }
+
+                                       /* enter test mode after irq */
+                                       if (handled > 0)
+                                               musb->test_mode = true;
+                                       break;
+#ifdef CONFIG_USB_MUSB_OTG
+                               case USB_DEVICE_B_HNP_ENABLE:
+                                       if (!musb->g.is_otg)
+                                               goto stall;
+                                       musb->g.b_hnp_enable = 1;
+                                       musb_try_b_hnp_enable(musb);
+                                       break;
+                               case USB_DEVICE_A_HNP_SUPPORT:
+                                       if (!musb->g.is_otg)
+                                               goto stall;
+                                       musb->g.a_hnp_support = 1;
+                                       break;
+                               case USB_DEVICE_A_ALT_HNP_SUPPORT:
+                                       if (!musb->g.is_otg)
+                                               goto stall;
+                                       musb->g.a_alt_hnp_support = 1;
+                                       break;
+#endif
+stall:
+                               default:
+                                       handled = -EINVAL;
+                                       break;
+                               }
+                               break;
+
+                       case USB_RECIP_INTERFACE:
+                               break;
+
+                       case USB_RECIP_ENDPOINT:{
+                               const u8                epnum =
+                                       ctrlrequest->wIndex & 0x0f;
+                               struct musb_ep          *musb_ep;
+                               struct musb_hw_ep       *ep;
+                               void __iomem            *regs;
+                               int                     is_in;
+                               u16                     csr;
+
+                               if (epnum == 0
+                                               || epnum >= MUSB_C_NUM_EPS
+                                               || ctrlrequest->wValue
+                                                       != USB_ENDPOINT_HALT)
+                                       break;
+
+                               ep = musb->endpoints + epnum;
+                               regs = ep->regs;
+                               is_in = ctrlrequest->wIndex & USB_DIR_IN;
+                               if (is_in)
+                                       musb_ep = &ep->ep_in;
+                               else
+                                       musb_ep = &ep->ep_out;
+                               if (!musb_ep->desc)
+                                       break;
+
+                               musb_ep_select(mbase, epnum);
+                               if (is_in) {
+                                       csr = musb_readw(regs,
+                                                       MUSB_TXCSR);
+                                       if (csr & MUSB_TXCSR_FIFONOTEMPTY)
+                                               csr |= MUSB_TXCSR_FLUSHFIFO;
+                                       csr |= MUSB_TXCSR_P_SENDSTALL
+                                               | MUSB_TXCSR_CLRDATATOG
+                                               | MUSB_TXCSR_P_WZC_BITS;
+                                       musb_writew(regs, MUSB_TXCSR,
+                                                       csr);
+                               } else {
+                                       csr = musb_readw(regs,
+                                                       MUSB_RXCSR);
+                                       csr |= MUSB_RXCSR_P_SENDSTALL
+                                               | MUSB_RXCSR_FLUSHFIFO
+                                               | MUSB_RXCSR_CLRDATATOG
+                                               | MUSB_TXCSR_P_WZC_BITS;
+                                       musb_writew(regs, MUSB_RXCSR,
+                                                       csr);
+                               }
+
+                               /* select ep0 again */
+                               musb_ep_select(mbase, 0);
+                               handled = 1;
+                               } break;
+
+                       default:
+                               /* class, vendor, etc ... delegate */
+                               handled = 0;
+                               break;
+                       }
+                       break;
+               default:
+                       /* delegate SET_CONFIGURATION, etc */
+                       handled = 0;
+               }
+       } else
+               handled = 0;
+       return handled;
+}
+
+/* we have an ep0out data packet
+ * Context:  caller holds controller lock
+ */
+static void ep0_rxstate(struct musb *musb)
+{
+       void __iomem            *regs = musb->control_ep->regs;
+       struct usb_request      *req;
+       u16                     tmp;
+
+       req = next_ep0_request(musb);
+
+       /* read packet and ack; or stall because of gadget driver bug:
+        * should have provided the rx buffer before setup() returned.
+        */
+       if (req) {
+               void            *buf = req->buf + req->actual;
+               unsigned        len = req->length - req->actual;
+
+               /* read the buffer */
+               tmp = musb_readb(regs, MUSB_COUNT0);
+               if (tmp > len) {
+                       req->status = -EOVERFLOW;
+                       tmp = len;
+               }
+               musb_read_fifo(&musb->endpoints[0], tmp, buf);
+               req->actual += tmp;
+               tmp = MUSB_CSR0_P_SVDRXPKTRDY;
+               if (tmp < 64 || req->actual == req->length) {
+                       musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
+                       tmp |= MUSB_CSR0_P_DATAEND;
+               } else
+                       req = NULL;
+       } else
+               tmp = MUSB_CSR0_P_SVDRXPKTRDY | MUSB_CSR0_P_SENDSTALL;
+
+
+       /* Completion handler may choose to stall, e.g. because the
+        * message just received holds invalid data.
+        */
+       if (req) {
+               musb->ackpend = tmp;
+               musb_g_ep0_giveback(musb, req);
+               if (!musb->ackpend)
+                       return;
+               musb->ackpend = 0;
+       }
+       musb_writew(regs, MUSB_CSR0, tmp);
+}
+
+/*
+ * transmitting to the host (IN), this code might be called from IRQ
+ * and from kernel thread.
+ *
+ * Context:  caller holds controller lock
+ */
+static void ep0_txstate(struct musb *musb)
+{
+       void __iomem            *regs = musb->control_ep->regs;
+       struct usb_request      *request = next_ep0_request(musb);
+       u16                     csr = MUSB_CSR0_TXPKTRDY;
+       u8                      *fifo_src;
+       u8                      fifo_count;
+
+       if (!request) {
+               /* WARN_ON(1); */
+               DBG(2, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0));
+               return;
+       }
+
+       /* load the data */
+       fifo_src = (u8 *) request->buf + request->actual;
+       fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE,
+               request->length - request->actual);
+       musb_write_fifo(&musb->endpoints[0], fifo_count, fifo_src);
+       request->actual += fifo_count;
+
+       /* update the flags */
+       if (fifo_count < MUSB_MAX_END0_PACKET
+                       || request->actual == request->length) {
+               musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT;
+               csr |= MUSB_CSR0_P_DATAEND;
+       } else
+               request = NULL;
+
+       /* report completions as soon as the fifo's loaded; there's no
+        * win in waiting till this last packet gets acked.  (other than
+        * very precise fault reporting, needed by USB TMC; possible with
+        * this hardware, but not usable from portable gadget drivers.)
+        */
+       if (request) {
+               musb->ackpend = csr;
+               musb_g_ep0_giveback(musb, request);
+               if (!musb->ackpend)
+                       return;
+               musb->ackpend = 0;
+       }
+
+       /* send it out, triggering a "txpktrdy cleared" irq */
+       musb_writew(regs, MUSB_CSR0, csr);
+}
+
+/*
+ * Read a SETUP packet (struct usb_ctrlrequest) from the hardware.
+ * Fields are left in USB byte-order.
+ *
+ * Context:  caller holds controller lock.
+ */
+static void
+musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req)
+{
+       struct usb_request      *r;
+       void __iomem            *regs = musb->control_ep->regs;
+
+       musb_read_fifo(&musb->endpoints[0], sizeof *req, (u8 *)req);
+
+       /* NOTE:  earlier 2.6 versions changed setup packets to host
+        * order, but now USB packets always stay in USB byte order.
+        */
+       DBG(3, "SETUP req%02x.%02x v%04x i%04x l%d\n",
+               req->bRequestType,
+               req->bRequest,
+               le16_to_cpu(req->wValue),
+               le16_to_cpu(req->wIndex),
+               le16_to_cpu(req->wLength));
+
+       /* clean up any leftover transfers */
+       r = next_ep0_request(musb);
+       if (r)
+               musb_g_ep0_giveback(musb, r);
+
+       /* For zero-data requests we want to delay the STATUS stage to
+        * avoid SETUPEND errors.  If we read data (OUT), delay accepting
+        * packets until there's a buffer to store them in.
+        *
+        * If we write data, the controller acts happier if we enable
+        * the TX FIFO right away, and give the controller a moment
+        * to switch modes...
+        */
+       musb->set_address = false;
+       musb->ackpend = MUSB_CSR0_P_SVDRXPKTRDY;
+       if (req->wLength == 0) {
+               if (req->bRequestType & USB_DIR_IN)
+                       musb->ackpend |= MUSB_CSR0_TXPKTRDY;
+               musb->ep0_state = MUSB_EP0_STAGE_ACKWAIT;
+       } else if (req->bRequestType & USB_DIR_IN) {
+               musb->ep0_state = MUSB_EP0_STAGE_TX;
+               musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDRXPKTRDY);
+               while ((musb_readw(regs, MUSB_CSR0)
+                               & MUSB_CSR0_RXPKTRDY) != 0)
+                       cpu_relax();
+               musb->ackpend = 0;
+       } else
+               musb->ep0_state = MUSB_EP0_STAGE_RX;
+}
+
+static int
+forward_to_driver(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest)
+__releases(musb->lock)
+__acquires(musb->lock)
+{
+       int retval;
+       if (!musb->gadget_driver)
+               return -EOPNOTSUPP;
+       spin_unlock(&musb->lock);
+       retval = musb->gadget_driver->setup(&musb->g, ctrlrequest);
+       spin_lock(&musb->lock);
+       return retval;
+}
+
+/*
+ * Handle peripheral ep0 interrupt
+ *
+ * Context: irq handler; we won't re-enter the driver that way.
+ */
+irqreturn_t musb_g_ep0_irq(struct musb *musb)
+{
+       u16             csr;
+       u16             len;
+       void __iomem    *mbase = musb->mregs;
+       void __iomem    *regs = musb->endpoints[0].regs;
+       irqreturn_t     retval = IRQ_NONE;
+
+       musb_ep_select(mbase, 0);       /* select ep0 */
+       csr = musb_readw(regs, MUSB_CSR0);
+       len = musb_readb(regs, MUSB_COUNT0);
+
+       DBG(4, "csr %04x, count %d, myaddr %d, ep0stage %s\n",
+                       csr, len,
+                       musb_readb(mbase, MUSB_FADDR),
+                       decode_ep0stage(musb->ep0_state));
+
+       /* I sent a stall.. need to acknowledge it now.. */
+       if (csr & MUSB_CSR0_P_SENTSTALL) {
+               musb_writew(regs, MUSB_CSR0,
+                               csr & ~MUSB_CSR0_P_SENTSTALL);
+               retval = IRQ_HANDLED;
+               musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+               csr = musb_readw(regs, MUSB_CSR0);
+       }
+
+       /* request ended "early" */
+       if (csr & MUSB_CSR0_P_SETUPEND) {
+               musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDSETUPEND);
+               retval = IRQ_HANDLED;
+               musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+               csr = musb_readw(regs, MUSB_CSR0);
+               /* NOTE:  request may need completion */
+       }
+
+       /* docs from Mentor only describe tx, rx, and idle/setup states.
+        * we need to handle nuances around status stages, and also the
+        * case where status and setup stages come back-to-back ...
+        */
+       switch (musb->ep0_state) {
+
+       case MUSB_EP0_STAGE_TX:
+               /* irq on clearing txpktrdy */
+               if ((csr & MUSB_CSR0_TXPKTRDY) == 0) {
+                       ep0_txstate(musb);
+                       retval = IRQ_HANDLED;
+               }
+               break;
+
+       case MUSB_EP0_STAGE_RX:
+               /* irq on set rxpktrdy */
+               if (csr & MUSB_CSR0_RXPKTRDY) {
+                       ep0_rxstate(musb);
+                       retval = IRQ_HANDLED;
+               }
+               break;
+
+       case MUSB_EP0_STAGE_STATUSIN:
+               /* end of sequence #2 (OUT/RX state) or #3 (no data) */
+
+               /* update address (if needed) only @ the end of the
+                * status phase per usb spec, which also guarantees
+                * we get 10 msec to receive this irq... until this
+                * is done we won't see the next packet.
+                */
+               if (musb->set_address) {
+                       musb->set_address = false;
+                       musb_writeb(mbase, MUSB_FADDR, musb->address);
+               }
+
+               /* enter test mode if needed (exit by reset) */
+               else if (musb->test_mode) {
+                       DBG(1, "entering TESTMODE\n");
+
+                       if (MUSB_TEST_PACKET == musb->test_mode_nr)
+                               musb_load_testpacket(musb);
+
+                       musb_writeb(mbase, MUSB_TESTMODE,
+                                       musb->test_mode_nr);
+               }
+               /* FALLTHROUGH */
+
+       case MUSB_EP0_STAGE_STATUSOUT:
+               /* end of sequence #1: write to host (TX state) */
+               {
+                       struct usb_request      *req;
+
+                       req = next_ep0_request(musb);
+                       if (req)
+                               musb_g_ep0_giveback(musb, req);
+               }
+               retval = IRQ_HANDLED;
+               musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+               /* FALLTHROUGH */
+
+       case MUSB_EP0_STAGE_SETUP:
+               if (csr & MUSB_CSR0_RXPKTRDY) {
+                       struct usb_ctrlrequest  setup;
+                       int                     handled = 0;
+
+                       if (len != 8) {
+                               ERR("SETUP packet len %d != 8 ?\n", len);
+                               break;
+                       }
+                       musb_read_setup(musb, &setup);
+                       retval = IRQ_HANDLED;
+
+                       /* sometimes the RESET won't be reported */
+                       if (unlikely(musb->g.speed == USB_SPEED_UNKNOWN)) {
+                               u8      power;
+
+                               printk(KERN_NOTICE "%s: peripheral reset "
+                                               "irq lost!\n",
+                                               musb_driver_name);
+                               power = musb_readb(mbase, MUSB_POWER);
+                               musb->g.speed = (power & MUSB_POWER_HSMODE)
+                                       ? USB_SPEED_HIGH : USB_SPEED_FULL;
+
+                       }
+
+                       switch (musb->ep0_state) {
+
+                       /* sequence #3 (no data stage), includes requests
+                        * we can't forward (notably SET_ADDRESS and the
+                        * device/endpoint feature set/clear operations)
+                        * plus SET_CONFIGURATION and others we must
+                        */
+                       case MUSB_EP0_STAGE_ACKWAIT:
+                               handled = service_zero_data_request(
+                                               musb, &setup);
+
+                               /* status stage might be immediate */
+                               if (handled > 0) {
+                                       musb->ackpend |= MUSB_CSR0_P_DATAEND;
+                                       musb->ep0_state =
+                                               MUSB_EP0_STAGE_STATUSIN;
+                               }
+                               break;
+
+                       /* sequence #1 (IN to host), includes GET_STATUS
+                        * requests that we can't forward, GET_DESCRIPTOR
+                        * and others that we must
+                        */
+                       case MUSB_EP0_STAGE_TX:
+                               handled = service_in_request(musb, &setup);
+                               if (handled > 0) {
+                                       musb->ackpend = MUSB_CSR0_TXPKTRDY
+                                               | MUSB_CSR0_P_DATAEND;
+                                       musb->ep0_state =
+                                               MUSB_EP0_STAGE_STATUSOUT;
+                               }
+                               break;
+
+                       /* sequence #2 (OUT from host), always forward */
+                       default:                /* MUSB_EP0_STAGE_RX */
+                               break;
+                       }
+
+                       DBG(3, "handled %d, csr %04x, ep0stage %s\n",
+                               handled, csr,
+                               decode_ep0stage(musb->ep0_state));
+
+                       /* unless we need to delegate this to the gadget
+                        * driver, we know how to wrap this up:  csr0 has
+                        * not yet been written.
+                        */
+                       if (handled < 0)
+                               goto stall;
+                       else if (handled > 0)
+                               goto finish;
+
+                       handled = forward_to_driver(musb, &setup);
+                       if (handled < 0) {
+                               musb_ep_select(mbase, 0);
+stall:
+                               DBG(3, "stall (%d)\n", handled);
+                               musb->ackpend |= MUSB_CSR0_P_SENDSTALL;
+                               musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+finish:
+                               musb_writew(regs, MUSB_CSR0,
+                                               musb->ackpend);
+                               musb->ackpend = 0;
+                       }
+               }
+               break;
+
+       case MUSB_EP0_STAGE_ACKWAIT:
+               /* This should not happen. But happens with tusb6010 with
+                * g_file_storage and high speed. Do nothing.
+                */
+               retval = IRQ_HANDLED;
+               break;
+
+       default:
+               /* "can't happen" */
+               WARN_ON(1);
+               musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SENDSTALL);
+               musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+               break;
+       }
+
+       return retval;
+}
+
+
+static int
+musb_g_ep0_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc)
+{
+       /* always enabled */
+       return -EINVAL;
+}
+
+static int musb_g_ep0_disable(struct usb_ep *e)
+{
+       /* always enabled */
+       return -EINVAL;
+}
+
+static int
+musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags)
+{
+       struct musb_ep          *ep;
+       struct musb_request     *req;
+       struct musb             *musb;
+       int                     status;
+       unsigned long           lockflags;
+       void __iomem            *regs;
+
+       if (!e || !r)
+               return -EINVAL;
+
+       ep = to_musb_ep(e);
+       musb = ep->musb;
+       regs = musb->control_ep->regs;
+
+       req = to_musb_request(r);
+       req->musb = musb;
+       req->request.actual = 0;
+       req->request.status = -EINPROGRESS;
+       req->tx = ep->is_in;
+
+       spin_lock_irqsave(&musb->lock, lockflags);
+
+       if (!list_empty(&ep->req_list)) {
+               status = -EBUSY;
+               goto cleanup;
+       }
+
+       switch (musb->ep0_state) {
+       case MUSB_EP0_STAGE_RX:         /* control-OUT data */
+       case MUSB_EP0_STAGE_TX:         /* control-IN data */
+       case MUSB_EP0_STAGE_ACKWAIT:    /* zero-length data */
+               status = 0;
+               break;
+       default:
+               DBG(1, "ep0 request queued in state %d\n",
+                               musb->ep0_state);
+               status = -EINVAL;
+               goto cleanup;
+       }
+
+       /* add request to the list */
+       list_add_tail(&(req->request.list), &(ep->req_list));
+
+       DBG(3, "queue to %s (%s), length=%d\n",
+                       ep->name, ep->is_in ? "IN/TX" : "OUT/RX",
+                       req->request.length);
+
+       musb_ep_select(musb->mregs, 0);
+
+       /* sequence #1, IN ... start writing the data */
+       if (musb->ep0_state == MUSB_EP0_STAGE_TX)
+               ep0_txstate(musb);
+
+       /* sequence #3, no-data ... issue IN status */
+       else if (musb->ep0_state == MUSB_EP0_STAGE_ACKWAIT) {
+               if (req->request.length)
+                       status = -EINVAL;
+               else {
+                       musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
+                       musb_writew(regs, MUSB_CSR0,
+                                       musb->ackpend | MUSB_CSR0_P_DATAEND);
+                       musb->ackpend = 0;
+                       musb_g_ep0_giveback(ep->musb, r);
+               }
+
+       /* else for sequence #2 (OUT), caller provides a buffer
+        * before the next packet arrives.  deferred responses
+        * (after SETUP is acked) are racey.
+        */
+       } else if (musb->ackpend) {
+               musb_writew(regs, MUSB_CSR0, musb->ackpend);
+               musb->ackpend = 0;
+       }
+
+cleanup:
+       spin_unlock_irqrestore(&musb->lock, lockflags);
+       return status;
+}
+
+static int musb_g_ep0_dequeue(struct usb_ep *ep, struct usb_request *req)
+{
+       /* we just won't support this */
+       return -EINVAL;
+}
+
+static int musb_g_ep0_halt(struct usb_ep *e, int value)
+{
+       struct musb_ep          *ep;
+       struct musb             *musb;
+       void __iomem            *base, *regs;
+       unsigned long           flags;
+       int                     status;
+       u16                     csr;
+
+       if (!e || !value)
+               return -EINVAL;
+
+       ep = to_musb_ep(e);
+       musb = ep->musb;
+       base = musb->mregs;
+       regs = musb->control_ep->regs;
+       status = 0;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       if (!list_empty(&ep->req_list)) {
+               status = -EBUSY;
+               goto cleanup;
+       }
+
+       musb_ep_select(base, 0);
+       csr = musb->ackpend;
+
+       switch (musb->ep0_state) {
+
+       /* Stalls are usually issued after parsing SETUP packet, either
+        * directly in irq context from setup() or else later.
+        */
+       case MUSB_EP0_STAGE_TX:         /* control-IN data */
+       case MUSB_EP0_STAGE_ACKWAIT:    /* STALL for zero-length data */
+       case MUSB_EP0_STAGE_RX:         /* control-OUT data */
+               csr = musb_readw(regs, MUSB_CSR0);
+               /* FALLTHROUGH */
+
+       /* It's also OK to issue stalls during callbacks when a non-empty
+        * DATA stage buffer has been read (or even written).
+        */
+       case MUSB_EP0_STAGE_STATUSIN:   /* control-OUT status */
+       case MUSB_EP0_STAGE_STATUSOUT:  /* control-IN status */
+
+               csr |= MUSB_CSR0_P_SENDSTALL;
+               musb_writew(regs, MUSB_CSR0, csr);
+               musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+               musb->ackpend = 0;
+               break;
+       default:
+               DBG(1, "ep0 can't halt in state %d\n", musb->ep0_state);
+               status = -EINVAL;
+       }
+
+cleanup:
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return status;
+}
+
+const struct usb_ep_ops musb_g_ep0_ops = {
+       .enable         = musb_g_ep0_enable,
+       .disable        = musb_g_ep0_disable,
+       .alloc_request  = musb_alloc_request,
+       .free_request   = musb_free_request,
+       .queue          = musb_g_ep0_queue,
+       .dequeue        = musb_g_ep0_dequeue,
+       .set_halt       = musb_g_ep0_halt,
+};
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
new file mode 100644 (file)
index 0000000..8b4be01
--- /dev/null
@@ -0,0 +1,2170 @@
+/*
+ * MUSB OTG driver host support
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+
+#include "musb_core.h"
+#include "musb_host.h"
+
+
+/* MUSB HOST status 22-mar-2006
+ *
+ * - There's still lots of partial code duplication for fault paths, so
+ *   they aren't handled as consistently as they need to be.
+ *
+ * - PIO mostly behaved when last tested.
+ *     + including ep0, with all usbtest cases 9, 10
+ *     + usbtest 14 (ep0out) doesn't seem to run at all
+ *     + double buffered OUT/TX endpoints saw stalls(!) with certain usbtest
+ *       configurations, but otherwise double buffering passes basic tests.
+ *     + for 2.6.N, for N > ~10, needs API changes for hcd framework.
+ *
+ * - DMA (CPPI) ... partially behaves, not currently recommended
+ *     + about 1/15 the speed of typical EHCI implementations (PCI)
+ *     + RX, all too often reqpkt seems to misbehave after tx
+ *     + TX, no known issues (other than evident silicon issue)
+ *
+ * - DMA (Mentor/OMAP) ...has at least toggle update problems
+ *
+ * - Still no traffic scheduling code to make NAKing for bulk or control
+ *   transfers unable to starve other requests; or to make efficient use
+ *   of hardware with periodic transfers.  (Note that network drivers
+ *   commonly post bulk reads that stay pending for a long time; these
+ *   would make very visible trouble.)
+ *
+ * - Not tested with HNP, but some SRP paths seem to behave.
+ *
+ * NOTE 24-August-2006:
+ *
+ * - Bulk traffic finally uses both sides of hardware ep1, freeing up an
+ *   extra endpoint for periodic use enabling hub + keybd + mouse.  That
+ *   mostly works, except that with "usbnet" it's easy to trigger cases
+ *   with "ping" where RX loses.  (a) ping to davinci, even "ping -f",
+ *   fine; but (b) ping _from_ davinci, even "ping -c 1", ICMP RX loses
+ *   although ARP RX wins.  (That test was done with a full speed link.)
+ */
+
+
+/*
+ * NOTE on endpoint usage:
+ *
+ * CONTROL transfers all go through ep0.  BULK ones go through dedicated IN
+ * and OUT endpoints ... hardware is dedicated for those "async" queue(s).
+ *
+ * (Yes, bulk _could_ use more of the endpoints than that, and would even
+ * benefit from it ... one remote device may easily be NAKing while others
+ * need to perform transfers in that same direction.  The same thing could
+ * be done in software though, assuming dma cooperates.)
+ *
+ * INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints.
+ * So far that scheduling is both dumb and optimistic:  the endpoint will be
+ * "claimed" until its software queue is no longer refilled.  No multiplexing
+ * of transfers between endpoints, or anything clever.
+ */
+
+
+static void musb_ep_program(struct musb *musb, u8 epnum,
+                       struct urb *urb, unsigned int nOut,
+                       u8 *buf, u32 len);
+
+/*
+ * Clear TX fifo. Needed to avoid BABBLE errors.
+ */
+static inline void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
+{
+       void __iomem    *epio = ep->regs;
+       u16             csr;
+       int             retries = 1000;
+
+       csr = musb_readw(epio, MUSB_TXCSR);
+       while (csr & MUSB_TXCSR_FIFONOTEMPTY) {
+               DBG(5, "Host TX FIFONOTEMPTY csr: %02x\n", csr);
+               csr |= MUSB_TXCSR_FLUSHFIFO;
+               musb_writew(epio, MUSB_TXCSR, csr);
+               csr = musb_readw(epio, MUSB_TXCSR);
+               if (retries-- < 1) {
+                       ERR("Could not flush host TX fifo: csr: %04x\n", csr);
+                       return;
+               }
+               mdelay(1);
+       }
+}
+
+/*
+ * Start transmit. Caller is responsible for locking shared resources.
+ * musb must be locked.
+ */
+static inline void musb_h_tx_start(struct musb_hw_ep *ep)
+{
+       u16     txcsr;
+
+       /* NOTE: no locks here; caller should lock and select EP */
+       if (ep->epnum) {
+               txcsr = musb_readw(ep->regs, MUSB_TXCSR);
+               txcsr |= MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_H_WZC_BITS;
+               musb_writew(ep->regs, MUSB_TXCSR, txcsr);
+       } else {
+               txcsr = MUSB_CSR0_H_SETUPPKT | MUSB_CSR0_TXPKTRDY;
+               musb_writew(ep->regs, MUSB_CSR0, txcsr);
+       }
+
+}
+
+static inline void cppi_host_txdma_start(struct musb_hw_ep *ep)
+{
+       u16     txcsr;
+
+       /* NOTE: no locks here; caller should lock and select EP */
+       txcsr = musb_readw(ep->regs, MUSB_TXCSR);
+       txcsr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_H_WZC_BITS;
+       musb_writew(ep->regs, MUSB_TXCSR, txcsr);
+}
+
+/*
+ * Start the URB at the front of an endpoint's queue
+ * end must be claimed from the caller.
+ *
+ * Context: controller locked, irqs blocked
+ */
+static void
+musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
+{
+       u16                     frame;
+       u32                     len;
+       void                    *buf;
+       void __iomem            *mbase =  musb->mregs;
+       struct urb              *urb = next_urb(qh);
+       struct musb_hw_ep       *hw_ep = qh->hw_ep;
+       unsigned                pipe = urb->pipe;
+       u8                      address = usb_pipedevice(pipe);
+       int                     epnum = hw_ep->epnum;
+
+       /* initialize software qh state */
+       qh->offset = 0;
+       qh->segsize = 0;
+
+       /* gather right source of data */
+       switch (qh->type) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               /* control transfers always start with SETUP */
+               is_in = 0;
+               hw_ep->out_qh = qh;
+               musb->ep0_stage = MUSB_EP0_START;
+               buf = urb->setup_packet;
+               len = 8;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               qh->iso_idx = 0;
+               qh->frame = 0;
+               buf = urb->transfer_buffer + urb->iso_frame_desc[0].offset;
+               len = urb->iso_frame_desc[0].length;
+               break;
+       default:                /* bulk, interrupt */
+               buf = urb->transfer_buffer;
+               len = urb->transfer_buffer_length;
+       }
+
+       DBG(4, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n",
+                       qh, urb, address, qh->epnum,
+                       is_in ? "in" : "out",
+                       ({char *s; switch (qh->type) {
+                       case USB_ENDPOINT_XFER_CONTROL: s = ""; break;
+                       case USB_ENDPOINT_XFER_BULK:    s = "-bulk"; break;
+                       case USB_ENDPOINT_XFER_ISOC:    s = "-iso"; break;
+                       default:                        s = "-intr"; break;
+                       }; s; }),
+                       epnum, buf, len);
+
+       /* Configure endpoint */
+       if (is_in || hw_ep->is_shared_fifo)
+               hw_ep->in_qh = qh;
+       else
+               hw_ep->out_qh = qh;
+       musb_ep_program(musb, epnum, urb, !is_in, buf, len);
+
+       /* transmit may have more work: start it when it is time */
+       if (is_in)
+               return;
+
+       /* determine if the time is right for a periodic transfer */
+       switch (qh->type) {
+       case USB_ENDPOINT_XFER_ISOC:
+       case USB_ENDPOINT_XFER_INT:
+               DBG(3, "check whether there's still time for periodic Tx\n");
+               qh->iso_idx = 0;
+               frame = musb_readw(mbase, MUSB_FRAME);
+               /* FIXME this doesn't implement that scheduling policy ...
+                * or handle framecounter wrapping
+                */
+               if ((urb->transfer_flags & URB_ISO_ASAP)
+                               || (frame >= urb->start_frame)) {
+                       /* REVISIT the SOF irq handler shouldn't duplicate
+                        * this code; and we don't init urb->start_frame...
+                        */
+                       qh->frame = 0;
+                       goto start;
+               } else {
+                       qh->frame = urb->start_frame;
+                       /* enable SOF interrupt so we can count down */
+                       DBG(1, "SOF for %d\n", epnum);
+#if 1 /* ifndef        CONFIG_ARCH_DAVINCI */
+                       musb_writeb(mbase, MUSB_INTRUSBE, 0xff);
+#endif
+               }
+               break;
+       default:
+start:
+               DBG(4, "Start TX%d %s\n", epnum,
+                       hw_ep->tx_channel ? "dma" : "pio");
+
+               if (!hw_ep->tx_channel)
+                       musb_h_tx_start(hw_ep);
+               else if (is_cppi_enabled() || tusb_dma_omap())
+                       cppi_host_txdma_start(hw_ep);
+       }
+}
+
+/* caller owns controller lock, irqs are blocked */
+static void
+__musb_giveback(struct musb *musb, struct urb *urb, int status)
+__releases(musb->lock)
+__acquires(musb->lock)
+{
+       DBG(({ int level; switch (urb->status) {
+                               case 0:
+                                       level = 4;
+                                       break;
+                               /* common/boring faults */
+                               case -EREMOTEIO:
+                               case -ESHUTDOWN:
+                               case -ECONNRESET:
+                               case -EPIPE:
+                                       level = 3;
+                                       break;
+                               default:
+                                       level = 2;
+                                       break;
+                               }; level; }),
+                       "complete %p (%d), dev%d ep%d%s, %d/%d\n",
+                       urb, urb->status,
+                       usb_pipedevice(urb->pipe),
+                       usb_pipeendpoint(urb->pipe),
+                       usb_pipein(urb->pipe) ? "in" : "out",
+                       urb->actual_length, urb->transfer_buffer_length
+                       );
+
+       spin_unlock(&musb->lock);
+       usb_hcd_giveback_urb(musb_to_hcd(musb), urb, status);
+       spin_lock(&musb->lock);
+}
+
+/* for bulk/interrupt endpoints only */
+static inline void
+musb_save_toggle(struct musb_hw_ep *ep, int is_in, struct urb *urb)
+{
+       struct usb_device       *udev = urb->dev;
+       u16                     csr;
+       void __iomem            *epio = ep->regs;
+       struct musb_qh          *qh;
+
+       /* FIXME:  the current Mentor DMA code seems to have
+        * problems getting toggle correct.
+        */
+
+       if (is_in || ep->is_shared_fifo)
+               qh = ep->in_qh;
+       else
+               qh = ep->out_qh;
+
+       if (!is_in) {
+               csr = musb_readw(epio, MUSB_TXCSR);
+               usb_settoggle(udev, qh->epnum, 1,
+                       (csr & MUSB_TXCSR_H_DATATOGGLE)
+                               ? 1 : 0);
+       } else {
+               csr = musb_readw(epio, MUSB_RXCSR);
+               usb_settoggle(udev, qh->epnum, 0,
+                       (csr & MUSB_RXCSR_H_DATATOGGLE)
+                               ? 1 : 0);
+       }
+}
+
+/* caller owns controller lock, irqs are blocked */
+static struct musb_qh *
+musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
+{
+       int                     is_in;
+       struct musb_hw_ep       *ep = qh->hw_ep;
+       struct musb             *musb = ep->musb;
+       int                     ready = qh->is_ready;
+
+       if (ep->is_shared_fifo)
+               is_in = 1;
+       else
+               is_in = usb_pipein(urb->pipe);
+
+       /* save toggle eagerly, for paranoia */
+       switch (qh->type) {
+       case USB_ENDPOINT_XFER_BULK:
+       case USB_ENDPOINT_XFER_INT:
+               musb_save_toggle(ep, is_in, urb);
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (status == 0 && urb->error_count)
+                       status = -EXDEV;
+               break;
+       }
+
+       usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb);
+
+       qh->is_ready = 0;
+       __musb_giveback(musb, urb, status);
+       qh->is_ready = ready;
+
+       /* reclaim resources (and bandwidth) ASAP; deschedule it, and
+        * invalidate qh as soon as list_empty(&hep->urb_list)
+        */
+       if (list_empty(&qh->hep->urb_list)) {
+               struct list_head        *head;
+
+               if (is_in)
+                       ep->rx_reinit = 1;
+               else
+                       ep->tx_reinit = 1;
+
+               /* clobber old pointers to this qh */
+               if (is_in || ep->is_shared_fifo)
+                       ep->in_qh = NULL;
+               else
+                       ep->out_qh = NULL;
+               qh->hep->hcpriv = NULL;
+
+               switch (qh->type) {
+
+               case USB_ENDPOINT_XFER_ISOC:
+               case USB_ENDPOINT_XFER_INT:
+                       /* this is where periodic bandwidth should be
+                        * de-allocated if it's tracked and allocated;
+                        * and where we'd update the schedule tree...
+                        */
+                       musb->periodic[ep->epnum] = NULL;
+                       kfree(qh);
+                       qh = NULL;
+                       break;
+
+               case USB_ENDPOINT_XFER_CONTROL:
+               case USB_ENDPOINT_XFER_BULK:
+                       /* fifo policy for these lists, except that NAKing
+                        * should rotate a qh to the end (for fairness).
+                        */
+                       head = qh->ring.prev;
+                       list_del(&qh->ring);
+                       kfree(qh);
+                       qh = first_qh(head);
+                       break;
+               }
+       }
+       return qh;
+}
+
+/*
+ * Advance this hardware endpoint's queue, completing the specified urb and
+ * advancing to either the next urb queued to that qh, or else invalidating
+ * that qh and advancing to the next qh scheduled after the current one.
+ *
+ * Context: caller owns controller lock, irqs are blocked
+ */
+static void
+musb_advance_schedule(struct musb *musb, struct urb *urb,
+               struct musb_hw_ep *hw_ep, int is_in)
+{
+       struct musb_qh  *qh;
+
+       if (is_in || hw_ep->is_shared_fifo)
+               qh = hw_ep->in_qh;
+       else
+               qh = hw_ep->out_qh;
+
+       if (urb->status == -EINPROGRESS)
+               qh = musb_giveback(qh, urb, 0);
+       else
+               qh = musb_giveback(qh, urb, urb->status);
+
+       if (qh && qh->is_ready && !list_empty(&qh->hep->urb_list)) {
+               DBG(4, "... next ep%d %cX urb %p\n",
+                               hw_ep->epnum, is_in ? 'R' : 'T',
+                               next_urb(qh));
+               musb_start_urb(musb, is_in, qh);
+       }
+}
+
+static inline u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr)
+{
+       /* we don't want fifo to fill itself again;
+        * ignore dma (various models),
+        * leave toggle alone (may not have been saved yet)
+        */
+       csr |= MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_RXPKTRDY;
+       csr &= ~(MUSB_RXCSR_H_REQPKT
+               | MUSB_RXCSR_H_AUTOREQ
+               | MUSB_RXCSR_AUTOCLEAR);
+
+       /* write 2x to allow double buffering */
+       musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
+       musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
+
+       /* flush writebuffer */
+       return musb_readw(hw_ep->regs, MUSB_RXCSR);
+}
+
+/*
+ * PIO RX for a packet (or part of it).
+ */
+static bool
+musb_host_packet_rx(struct musb *musb, struct urb *urb, u8 epnum, u8 iso_err)
+{
+       u16                     rx_count;
+       u8                      *buf;
+       u16                     csr;
+       bool                    done = false;
+       u32                     length;
+       int                     do_flush = 0;
+       struct musb_hw_ep       *hw_ep = musb->endpoints + epnum;
+       void __iomem            *epio = hw_ep->regs;
+       struct musb_qh          *qh = hw_ep->in_qh;
+       int                     pipe = urb->pipe;
+       void                    *buffer = urb->transfer_buffer;
+
+       /* musb_ep_select(mbase, epnum); */
+       rx_count = musb_readw(epio, MUSB_RXCOUNT);
+       DBG(3, "RX%d count %d, buffer %p len %d/%d\n", epnum, rx_count,
+                       urb->transfer_buffer, qh->offset,
+                       urb->transfer_buffer_length);
+
+       /* unload FIFO */
+       if (usb_pipeisoc(pipe)) {
+               int                                     status = 0;
+               struct usb_iso_packet_descriptor        *d;
+
+               if (iso_err) {
+                       status = -EILSEQ;
+                       urb->error_count++;
+               }
+
+               d = urb->iso_frame_desc + qh->iso_idx;
+               buf = buffer + d->offset;
+               length = d->length;
+               if (rx_count > length) {
+                       if (status == 0) {
+                               status = -EOVERFLOW;
+                               urb->error_count++;
+                       }
+                       DBG(2, "** OVERFLOW %d into %d\n", rx_count, length);
+                       do_flush = 1;
+               } else
+                       length = rx_count;
+               urb->actual_length += length;
+               d->actual_length = length;
+
+               d->status = status;
+
+               /* see if we are done */
+               done = (++qh->iso_idx >= urb->number_of_packets);
+       } else {
+               /* non-isoch */
+               buf = buffer + qh->offset;
+               length = urb->transfer_buffer_length - qh->offset;
+               if (rx_count > length) {
+                       if (urb->status == -EINPROGRESS)
+                               urb->status = -EOVERFLOW;
+                       DBG(2, "** OVERFLOW %d into %d\n", rx_count, length);
+                       do_flush = 1;
+               } else
+                       length = rx_count;
+               urb->actual_length += length;
+               qh->offset += length;
+
+               /* see if we are done */
+               done = (urb->actual_length == urb->transfer_buffer_length)
+                       || (rx_count < qh->maxpacket)
+                       || (urb->status != -EINPROGRESS);
+               if (done
+                               && (urb->status == -EINPROGRESS)
+                               && (urb->transfer_flags & URB_SHORT_NOT_OK)
+                               && (urb->actual_length
+                                       < urb->transfer_buffer_length))
+                       urb->status = -EREMOTEIO;
+       }
+
+       musb_read_fifo(hw_ep, length, buf);
+
+       csr = musb_readw(epio, MUSB_RXCSR);
+       csr |= MUSB_RXCSR_H_WZC_BITS;
+       if (unlikely(do_flush))
+               musb_h_flush_rxfifo(hw_ep, csr);
+       else {
+               /* REVISIT this assumes AUTOCLEAR is never set */
+               csr &= ~(MUSB_RXCSR_RXPKTRDY | MUSB_RXCSR_H_REQPKT);
+               if (!done)
+                       csr |= MUSB_RXCSR_H_REQPKT;
+               musb_writew(epio, MUSB_RXCSR, csr);
+       }
+
+       return done;
+}
+
+/* we don't always need to reinit a given side of an endpoint...
+ * when we do, use tx/rx reinit routine and then construct a new CSR
+ * to address data toggle, NYET, and DMA or PIO.
+ *
+ * it's possible that driver bugs (especially for DMA) or aborting a
+ * transfer might have left the endpoint busier than it should be.
+ * the busy/not-empty tests are basically paranoia.
+ */
+static void
+musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
+{
+       u16     csr;
+
+       /* NOTE:  we know the "rx" fifo reinit never triggers for ep0.
+        * That always uses tx_reinit since ep0 repurposes TX register
+        * offsets; the initial SETUP packet is also a kind of OUT.
+        */
+
+       /* if programmed for Tx, put it in RX mode */
+       if (ep->is_shared_fifo) {
+               csr = musb_readw(ep->regs, MUSB_TXCSR);
+               if (csr & MUSB_TXCSR_MODE) {
+                       musb_h_tx_flush_fifo(ep);
+                       musb_writew(ep->regs, MUSB_TXCSR,
+                                       MUSB_TXCSR_FRCDATATOG);
+               }
+               /* clear mode (and everything else) to enable Rx */
+               musb_writew(ep->regs, MUSB_TXCSR, 0);
+
+       /* scrub all previous state, clearing toggle */
+       } else {
+               csr = musb_readw(ep->regs, MUSB_RXCSR);
+               if (csr & MUSB_RXCSR_RXPKTRDY)
+                       WARNING("rx%d, packet/%d ready?\n", ep->epnum,
+                               musb_readw(ep->regs, MUSB_RXCOUNT));
+
+               musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
+       }
+
+       /* target addr and (for multipoint) hub addr/port */
+       if (musb->is_multipoint) {
+               musb_writeb(ep->target_regs, MUSB_RXFUNCADDR,
+                       qh->addr_reg);
+               musb_writeb(ep->target_regs, MUSB_RXHUBADDR,
+                       qh->h_addr_reg);
+               musb_writeb(ep->target_regs, MUSB_RXHUBPORT,
+                       qh->h_port_reg);
+       } else
+               musb_writeb(musb->mregs, MUSB_FADDR, qh->addr_reg);
+
+       /* protocol/endpoint, interval/NAKlimit, i/o size */
+       musb_writeb(ep->regs, MUSB_RXTYPE, qh->type_reg);
+       musb_writeb(ep->regs, MUSB_RXINTERVAL, qh->intv_reg);
+       /* NOTE: bulk combining rewrites high bits of maxpacket */
+       musb_writew(ep->regs, MUSB_RXMAXP, qh->maxpacket);
+
+       ep->rx_reinit = 0;
+}
+
+
+/*
+ * Program an HDRC endpoint as per the given URB
+ * Context: irqs blocked, controller lock held
+ */
+static void musb_ep_program(struct musb *musb, u8 epnum,
+                       struct urb *urb, unsigned int is_out,
+                       u8 *buf, u32 len)
+{
+       struct dma_controller   *dma_controller;
+       struct dma_channel      *dma_channel;
+       u8                      dma_ok;
+       void __iomem            *mbase = musb->mregs;
+       struct musb_hw_ep       *hw_ep = musb->endpoints + epnum;
+       void __iomem            *epio = hw_ep->regs;
+       struct musb_qh          *qh;
+       u16                     packet_sz;
+
+       if (!is_out || hw_ep->is_shared_fifo)
+               qh = hw_ep->in_qh;
+       else
+               qh = hw_ep->out_qh;
+
+       packet_sz = qh->maxpacket;
+
+       DBG(3, "%s hw%d urb %p spd%d dev%d ep%d%s "
+                               "h_addr%02x h_port%02x bytes %d\n",
+                       is_out ? "-->" : "<--",
+                       epnum, urb, urb->dev->speed,
+                       qh->addr_reg, qh->epnum, is_out ? "out" : "in",
+                       qh->h_addr_reg, qh->h_port_reg,
+                       len);
+
+       musb_ep_select(mbase, epnum);
+
+       /* candidate for DMA? */
+       dma_controller = musb->dma_controller;
+       if (is_dma_capable() && epnum && dma_controller) {
+               dma_channel = is_out ? hw_ep->tx_channel : hw_ep->rx_channel;
+               if (!dma_channel) {
+                       dma_channel = dma_controller->channel_alloc(
+                                       dma_controller, hw_ep, is_out);
+                       if (is_out)
+                               hw_ep->tx_channel = dma_channel;
+                       else
+                               hw_ep->rx_channel = dma_channel;
+               }
+       } else
+               dma_channel = NULL;
+
+       /* make sure we clear DMAEnab, autoSet bits from previous run */
+
+       /* OUT/transmit/EP0 or IN/receive? */
+       if (is_out) {
+               u16     csr;
+               u16     int_txe;
+               u16     load_count;
+
+               csr = musb_readw(epio, MUSB_TXCSR);
+
+               /* disable interrupt in case we flush */
+               int_txe = musb_readw(mbase, MUSB_INTRTXE);
+               musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
+
+               /* general endpoint setup */
+               if (epnum) {
+                       /* ASSERT:  TXCSR_DMAENAB was already cleared */
+
+                       /* flush all old state, set default */
+                       musb_h_tx_flush_fifo(hw_ep);
+                       csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT
+                                       | MUSB_TXCSR_DMAMODE
+                                       | MUSB_TXCSR_FRCDATATOG
+                                       | MUSB_TXCSR_H_RXSTALL
+                                       | MUSB_TXCSR_H_ERROR
+                                       | MUSB_TXCSR_TXPKTRDY
+                                       );
+                       csr |= MUSB_TXCSR_MODE;
+
+                       if (usb_gettoggle(urb->dev,
+                                       qh->epnum, 1))
+                               csr |= MUSB_TXCSR_H_WR_DATATOGGLE
+                                       | MUSB_TXCSR_H_DATATOGGLE;
+                       else
+                               csr |= MUSB_TXCSR_CLRDATATOG;
+
+                       /* twice in case of double packet buffering */
+                       musb_writew(epio, MUSB_TXCSR, csr);
+                       /* REVISIT may need to clear FLUSHFIFO ... */
+                       musb_writew(epio, MUSB_TXCSR, csr);
+                       csr = musb_readw(epio, MUSB_TXCSR);
+               } else {
+                       /* endpoint 0: just flush */
+                       musb_writew(epio, MUSB_CSR0,
+                               csr | MUSB_CSR0_FLUSHFIFO);
+                       musb_writew(epio, MUSB_CSR0,
+                               csr | MUSB_CSR0_FLUSHFIFO);
+               }
+
+               /* target addr and (for multipoint) hub addr/port */
+               if (musb->is_multipoint) {
+                       musb_writeb(mbase,
+                               MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR),
+                               qh->addr_reg);
+                       musb_writeb(mbase,
+                               MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR),
+                               qh->h_addr_reg);
+                       musb_writeb(mbase,
+                               MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT),
+                               qh->h_port_reg);
+/* FIXME if !epnum, do the same for RX ... */
+               } else
+                       musb_writeb(mbase, MUSB_FADDR, qh->addr_reg);
+
+               /* protocol/endpoint/interval/NAKlimit */
+               if (epnum) {
+                       musb_writeb(epio, MUSB_TXTYPE, qh->type_reg);
+                       if (can_bulk_split(musb, qh->type))
+                               musb_writew(epio, MUSB_TXMAXP,
+                                       packet_sz
+                                       | ((hw_ep->max_packet_sz_tx /
+                                               packet_sz) - 1) << 11);
+                       else
+                               musb_writew(epio, MUSB_TXMAXP,
+                                       packet_sz);
+                       musb_writeb(epio, MUSB_TXINTERVAL, qh->intv_reg);
+               } else {
+                       musb_writeb(epio, MUSB_NAKLIMIT0, qh->intv_reg);
+                       if (musb->is_multipoint)
+                               musb_writeb(epio, MUSB_TYPE0,
+                                               qh->type_reg);
+               }
+
+               if (can_bulk_split(musb, qh->type))
+                       load_count = min((u32) hw_ep->max_packet_sz_tx,
+                                               len);
+               else
+                       load_count = min((u32) packet_sz, len);
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+               if (dma_channel) {
+
+                       /* clear previous state */
+                       csr = musb_readw(epio, MUSB_TXCSR);
+                       csr &= ~(MUSB_TXCSR_AUTOSET
+                               | MUSB_TXCSR_DMAMODE
+                               | MUSB_TXCSR_DMAENAB);
+                       csr |= MUSB_TXCSR_MODE;
+                       musb_writew(epio, MUSB_TXCSR,
+                               csr | MUSB_TXCSR_MODE);
+
+                       qh->segsize = min(len, dma_channel->max_len);
+
+                       if (qh->segsize <= packet_sz)
+                               dma_channel->desired_mode = 0;
+                       else
+                               dma_channel->desired_mode = 1;
+
+
+                       if (dma_channel->desired_mode == 0) {
+                               csr &= ~(MUSB_TXCSR_AUTOSET
+                                       | MUSB_TXCSR_DMAMODE);
+                               csr |= (MUSB_TXCSR_DMAENAB);
+                                       /* against programming guide */
+                       } else
+                               csr |= (MUSB_TXCSR_AUTOSET
+                                       | MUSB_TXCSR_DMAENAB
+                                       | MUSB_TXCSR_DMAMODE);
+
+                       musb_writew(epio, MUSB_TXCSR, csr);
+
+                       dma_ok = dma_controller->channel_program(
+                                       dma_channel, packet_sz,
+                                       dma_channel->desired_mode,
+                                       urb->transfer_dma,
+                                       qh->segsize);
+                       if (dma_ok) {
+                               load_count = 0;
+                       } else {
+                               dma_controller->channel_release(dma_channel);
+                               if (is_out)
+                                       hw_ep->tx_channel = NULL;
+                               else
+                                       hw_ep->rx_channel = NULL;
+                               dma_channel = NULL;
+                       }
+               }
+#endif
+
+               /* candidate for DMA */
+               if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
+
+                       /* program endpoint CSRs first, then setup DMA.
+                        * assume CPPI setup succeeds.
+                        * defer enabling dma.
+                        */
+                       csr = musb_readw(epio, MUSB_TXCSR);
+                       csr &= ~(MUSB_TXCSR_AUTOSET
+                                       | MUSB_TXCSR_DMAMODE
+                                       | MUSB_TXCSR_DMAENAB);
+                       csr |= MUSB_TXCSR_MODE;
+                       musb_writew(epio, MUSB_TXCSR,
+                               csr | MUSB_TXCSR_MODE);
+
+                       dma_channel->actual_len = 0L;
+                       qh->segsize = len;
+
+                       /* TX uses "rndis" mode automatically, but needs help
+                        * to identify the zero-length-final-packet case.
+                        */
+                       dma_ok = dma_controller->channel_program(
+                                       dma_channel, packet_sz,
+                                       (urb->transfer_flags
+                                                       & URB_ZERO_PACKET)
+                                               == URB_ZERO_PACKET,
+                                       urb->transfer_dma,
+                                       qh->segsize);
+                       if (dma_ok) {
+                               load_count = 0;
+                       } else {
+                               dma_controller->channel_release(dma_channel);
+                               hw_ep->tx_channel = NULL;
+                               dma_channel = NULL;
+
+                               /* REVISIT there's an error path here that
+                                * needs handling:  can't do dma, but
+                                * there's no pio buffer address...
+                                */
+                       }
+               }
+
+               if (load_count) {
+                       /* ASSERT:  TXCSR_DMAENAB was already cleared */
+
+                       /* PIO to load FIFO */
+                       qh->segsize = load_count;
+                       musb_write_fifo(hw_ep, load_count, buf);
+                       csr = musb_readw(epio, MUSB_TXCSR);
+                       csr &= ~(MUSB_TXCSR_DMAENAB
+                               | MUSB_TXCSR_DMAMODE
+                               | MUSB_TXCSR_AUTOSET);
+                       /* write CSR */
+                       csr |= MUSB_TXCSR_MODE;
+
+                       if (epnum)
+                               musb_writew(epio, MUSB_TXCSR, csr);
+               }
+
+               /* re-enable interrupt */
+               musb_writew(mbase, MUSB_INTRTXE, int_txe);
+
+       /* IN/receive */
+       } else {
+               u16     csr;
+
+               if (hw_ep->rx_reinit) {
+                       musb_rx_reinit(musb, qh, hw_ep);
+
+                       /* init new state: toggle and NYET, maybe DMA later */
+                       if (usb_gettoggle(urb->dev, qh->epnum, 0))
+                               csr = MUSB_RXCSR_H_WR_DATATOGGLE
+                                       | MUSB_RXCSR_H_DATATOGGLE;
+                       else
+                               csr = 0;
+                       if (qh->type == USB_ENDPOINT_XFER_INT)
+                               csr |= MUSB_RXCSR_DISNYET;
+
+               } else {
+                       csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
+
+                       if (csr & (MUSB_RXCSR_RXPKTRDY
+                                       | MUSB_RXCSR_DMAENAB
+                                       | MUSB_RXCSR_H_REQPKT))
+                               ERR("broken !rx_reinit, ep%d csr %04x\n",
+                                               hw_ep->epnum, csr);
+
+                       /* scrub any stale state, leaving toggle alone */
+                       csr &= MUSB_RXCSR_DISNYET;
+               }
+
+               /* kick things off */
+
+               if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
+                       /* candidate for DMA */
+                       if (dma_channel) {
+                               dma_channel->actual_len = 0L;
+                               qh->segsize = len;
+
+                               /* AUTOREQ is in a DMA register */
+                               musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
+                               csr = musb_readw(hw_ep->regs,
+                                               MUSB_RXCSR);
+
+                               /* unless caller treats short rx transfers as
+                                * errors, we dare not queue multiple transfers.
+                                */
+                               dma_ok = dma_controller->channel_program(
+                                               dma_channel, packet_sz,
+                                               !(urb->transfer_flags
+                                                       & URB_SHORT_NOT_OK),
+                                               urb->transfer_dma,
+                                               qh->segsize);
+                               if (!dma_ok) {
+                                       dma_controller->channel_release(
+                                                       dma_channel);
+                                       hw_ep->rx_channel = NULL;
+                                       dma_channel = NULL;
+                               } else
+                                       csr |= MUSB_RXCSR_DMAENAB;
+                       }
+               }
+
+               csr |= MUSB_RXCSR_H_REQPKT;
+               DBG(7, "RXCSR%d := %04x\n", epnum, csr);
+               musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
+               csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
+       }
+}
+
+
+/*
+ * Service the default endpoint (ep0) as host.
+ * Return true until it's time to start the status stage.
+ */
+static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb)
+{
+       bool                     more = false;
+       u8                      *fifo_dest = NULL;
+       u16                     fifo_count = 0;
+       struct musb_hw_ep       *hw_ep = musb->control_ep;
+       struct musb_qh          *qh = hw_ep->in_qh;
+       struct usb_ctrlrequest  *request;
+
+       switch (musb->ep0_stage) {
+       case MUSB_EP0_IN:
+               fifo_dest = urb->transfer_buffer + urb->actual_length;
+               fifo_count = min(len, ((u16) (urb->transfer_buffer_length
+                                       - urb->actual_length)));
+               if (fifo_count < len)
+                       urb->status = -EOVERFLOW;
+
+               musb_read_fifo(hw_ep, fifo_count, fifo_dest);
+
+               urb->actual_length += fifo_count;
+               if (len < qh->maxpacket) {
+                       /* always terminate on short read; it's
+                        * rarely reported as an error.
+                        */
+               } else if (urb->actual_length <
+                               urb->transfer_buffer_length)
+                       more = true;
+               break;
+       case MUSB_EP0_START:
+               request = (struct usb_ctrlrequest *) urb->setup_packet;
+
+               if (!request->wLength) {
+                       DBG(4, "start no-DATA\n");
+                       break;
+               } else if (request->bRequestType & USB_DIR_IN) {
+                       DBG(4, "start IN-DATA\n");
+                       musb->ep0_stage = MUSB_EP0_IN;
+                       more = true;
+                       break;
+               } else {
+                       DBG(4, "start OUT-DATA\n");
+                       musb->ep0_stage = MUSB_EP0_OUT;
+                       more = true;
+               }
+               /* FALLTHROUGH */
+       case MUSB_EP0_OUT:
+               fifo_count = min(qh->maxpacket, ((u16)
+                               (urb->transfer_buffer_length
+                               - urb->actual_length)));
+
+               if (fifo_count) {
+                       fifo_dest = (u8 *) (urb->transfer_buffer
+                                       + urb->actual_length);
+                       DBG(3, "Sending %d bytes to %p\n",
+                                       fifo_count, fifo_dest);
+                       musb_write_fifo(hw_ep, fifo_count, fifo_dest);
+
+                       urb->actual_length += fifo_count;
+                       more = true;
+               }
+               break;
+       default:
+               ERR("bogus ep0 stage %d\n", musb->ep0_stage);
+               break;
+       }
+
+       return more;
+}
+
+/*
+ * Handle default endpoint interrupt as host. Only called in IRQ time
+ * from the LinuxIsr() interrupt service routine.
+ *
+ * called with controller irqlocked
+ */
+irqreturn_t musb_h_ep0_irq(struct musb *musb)
+{
+       struct urb              *urb;
+       u16                     csr, len;
+       int                     status = 0;
+       void __iomem            *mbase = musb->mregs;
+       struct musb_hw_ep       *hw_ep = musb->control_ep;
+       void __iomem            *epio = hw_ep->regs;
+       struct musb_qh          *qh = hw_ep->in_qh;
+       bool                    complete = false;
+       irqreturn_t             retval = IRQ_NONE;
+
+       /* ep0 only has one queue, "in" */
+       urb = next_urb(qh);
+
+       musb_ep_select(mbase, 0);
+       csr = musb_readw(epio, MUSB_CSR0);
+       len = (csr & MUSB_CSR0_RXPKTRDY)
+                       ? musb_readb(epio, MUSB_COUNT0)
+                       : 0;
+
+       DBG(4, "<== csr0 %04x, qh %p, count %d, urb %p, stage %d\n",
+               csr, qh, len, urb, musb->ep0_stage);
+
+       /* if we just did status stage, we are done */
+       if (MUSB_EP0_STATUS == musb->ep0_stage) {
+               retval = IRQ_HANDLED;
+               complete = true;
+       }
+
+       /* prepare status */
+       if (csr & MUSB_CSR0_H_RXSTALL) {
+               DBG(6, "STALLING ENDPOINT\n");
+               status = -EPIPE;
+
+       } else if (csr & MUSB_CSR0_H_ERROR) {
+               DBG(2, "no response, csr0 %04x\n", csr);
+               status = -EPROTO;
+
+       } else if (csr & MUSB_CSR0_H_NAKTIMEOUT) {
+               DBG(2, "control NAK timeout\n");
+
+               /* NOTE:  this code path would be a good place to PAUSE a
+                * control transfer, if another one is queued, so that
+                * ep0 is more likely to stay busy.
+                *
+                * if (qh->ring.next != &musb->control), then
+                * we have a candidate... NAKing is *NOT* an error
+                */
+               musb_writew(epio, MUSB_CSR0, 0);
+               retval = IRQ_HANDLED;
+       }
+
+       if (status) {
+               DBG(6, "aborting\n");
+               retval = IRQ_HANDLED;
+               if (urb)
+                       urb->status = status;
+               complete = true;
+
+               /* use the proper sequence to abort the transfer */
+               if (csr & MUSB_CSR0_H_REQPKT) {
+                       csr &= ~MUSB_CSR0_H_REQPKT;
+                       musb_writew(epio, MUSB_CSR0, csr);
+                       csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
+                       musb_writew(epio, MUSB_CSR0, csr);
+               } else {
+                       csr |= MUSB_CSR0_FLUSHFIFO;
+                       musb_writew(epio, MUSB_CSR0, csr);
+                       musb_writew(epio, MUSB_CSR0, csr);
+                       csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
+                       musb_writew(epio, MUSB_CSR0, csr);
+               }
+
+               musb_writeb(epio, MUSB_NAKLIMIT0, 0);
+
+               /* clear it */
+               musb_writew(epio, MUSB_CSR0, 0);
+       }
+
+       if (unlikely(!urb)) {
+               /* stop endpoint since we have no place for its data, this
+                * SHOULD NEVER HAPPEN! */
+               ERR("no URB for end 0\n");
+
+               musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO);
+               musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO);
+               musb_writew(epio, MUSB_CSR0, 0);
+
+               goto done;
+       }
+
+       if (!complete) {
+               /* call common logic and prepare response */
+               if (musb_h_ep0_continue(musb, len, urb)) {
+                       /* more packets required */
+                       csr = (MUSB_EP0_IN == musb->ep0_stage)
+                               ?  MUSB_CSR0_H_REQPKT : MUSB_CSR0_TXPKTRDY;
+               } else {
+                       /* data transfer complete; perform status phase */
+                       if (usb_pipeout(urb->pipe)
+                                       || !urb->transfer_buffer_length)
+                               csr = MUSB_CSR0_H_STATUSPKT
+                                       | MUSB_CSR0_H_REQPKT;
+                       else
+                               csr = MUSB_CSR0_H_STATUSPKT
+                                       | MUSB_CSR0_TXPKTRDY;
+
+                       /* flag status stage */
+                       musb->ep0_stage = MUSB_EP0_STATUS;
+
+                       DBG(5, "ep0 STATUS, csr %04x\n", csr);
+
+               }
+               musb_writew(epio, MUSB_CSR0, csr);
+               retval = IRQ_HANDLED;
+       } else
+               musb->ep0_stage = MUSB_EP0_IDLE;
+
+       /* call completion handler if done */
+       if (complete)
+               musb_advance_schedule(musb, urb, hw_ep, 1);
+done:
+       return retval;
+}
+
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+
+/* Host side TX (OUT) using Mentor DMA works as follows:
+       submit_urb ->
+               - if queue was empty, Program Endpoint
+               - ... which starts DMA to fifo in mode 1 or 0
+
+       DMA Isr (transfer complete) -> TxAvail()
+               - Stop DMA (~DmaEnab)   (<--- Alert ... currently happens
+                                       only in musb_cleanup_urb)
+               - TxPktRdy has to be set in mode 0 or for
+                       short packets in mode 1.
+*/
+
+#endif
+
+/* Service a Tx-Available or dma completion irq for the endpoint */
+void musb_host_tx(struct musb *musb, u8 epnum)
+{
+       int                     pipe;
+       bool                    done = false;
+       u16                     tx_csr;
+       size_t                  wLength = 0;
+       u8                      *buf = NULL;
+       struct urb              *urb;
+       struct musb_hw_ep       *hw_ep = musb->endpoints + epnum;
+       void __iomem            *epio = hw_ep->regs;
+       struct musb_qh          *qh = hw_ep->out_qh;
+       u32                     status = 0;
+       void __iomem            *mbase = musb->mregs;
+       struct dma_channel      *dma;
+
+       urb = next_urb(qh);
+
+       musb_ep_select(mbase, epnum);
+       tx_csr = musb_readw(epio, MUSB_TXCSR);
+
+       /* with CPPI, DMA sometimes triggers "extra" irqs */
+       if (!urb) {
+               DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
+               goto finish;
+       }
+
+       pipe = urb->pipe;
+       dma = is_dma_capable() ? hw_ep->tx_channel : NULL;
+       DBG(4, "OUT/TX%d end, csr %04x%s\n", epnum, tx_csr,
+                       dma ? ", dma" : "");
+
+       /* check for errors */
+       if (tx_csr & MUSB_TXCSR_H_RXSTALL) {
+               /* dma was disabled, fifo flushed */
+               DBG(3, "TX end %d stall\n", epnum);
+
+               /* stall; record URB status */
+               status = -EPIPE;
+
+       } else if (tx_csr & MUSB_TXCSR_H_ERROR) {
+               /* (NON-ISO) dma was disabled, fifo flushed */
+               DBG(3, "TX 3strikes on ep=%d\n", epnum);
+
+               status = -ETIMEDOUT;
+
+       } else if (tx_csr & MUSB_TXCSR_H_NAKTIMEOUT) {
+               DBG(6, "TX end=%d device not responding\n", epnum);
+
+               /* NOTE:  this code path would be a good place to PAUSE a
+                * transfer, if there's some other (nonperiodic) tx urb
+                * that could use this fifo.  (dma complicates it...)
+                *
+                * if (bulk && qh->ring.next != &musb->out_bulk), then
+                * we have a candidate... NAKing is *NOT* an error
+                */
+               musb_ep_select(mbase, epnum);
+               musb_writew(epio, MUSB_TXCSR,
+                               MUSB_TXCSR_H_WZC_BITS
+                               | MUSB_TXCSR_TXPKTRDY);
+               goto finish;
+       }
+
+       if (status) {
+               if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+                       dma->status = MUSB_DMA_STATUS_CORE_ABORT;
+                       (void) musb->dma_controller->channel_abort(dma);
+               }
+
+               /* do the proper sequence to abort the transfer in the
+                * usb core; the dma engine should already be stopped.
+                */
+               musb_h_tx_flush_fifo(hw_ep);
+               tx_csr &= ~(MUSB_TXCSR_AUTOSET
+                               | MUSB_TXCSR_DMAENAB
+                               | MUSB_TXCSR_H_ERROR
+                               | MUSB_TXCSR_H_RXSTALL
+                               | MUSB_TXCSR_H_NAKTIMEOUT
+                               );
+
+               musb_ep_select(mbase, epnum);
+               musb_writew(epio, MUSB_TXCSR, tx_csr);
+               /* REVISIT may need to clear FLUSHFIFO ... */
+               musb_writew(epio, MUSB_TXCSR, tx_csr);
+               musb_writeb(epio, MUSB_TXINTERVAL, 0);
+
+               done = true;
+       }
+
+       /* second cppi case */
+       if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+               DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
+               goto finish;
+
+       }
+
+       /* REVISIT this looks wrong... */
+       if (!status || dma || usb_pipeisoc(pipe)) {
+               if (dma)
+                       wLength = dma->actual_len;
+               else
+                       wLength = qh->segsize;
+               qh->offset += wLength;
+
+               if (usb_pipeisoc(pipe)) {
+                       struct usb_iso_packet_descriptor        *d;
+
+                       d = urb->iso_frame_desc + qh->iso_idx;
+                       d->actual_length = qh->segsize;
+                       if (++qh->iso_idx >= urb->number_of_packets) {
+                               done = true;
+                       } else {
+                               d++;
+                               buf = urb->transfer_buffer + d->offset;
+                               wLength = d->length;
+                       }
+               } else if (dma) {
+                       done = true;
+               } else {
+                       /* see if we need to send more data, or ZLP */
+                       if (qh->segsize < qh->maxpacket)
+                               done = true;
+                       else if (qh->offset == urb->transfer_buffer_length
+                                       && !(urb->transfer_flags
+                                               & URB_ZERO_PACKET))
+                               done = true;
+                       if (!done) {
+                               buf = urb->transfer_buffer
+                                               + qh->offset;
+                               wLength = urb->transfer_buffer_length
+                                               - qh->offset;
+                       }
+               }
+       }
+
+       /* urb->status != -EINPROGRESS means request has been faulted,
+        * so we must abort this transfer after cleanup
+        */
+       if (urb->status != -EINPROGRESS) {
+               done = true;
+               if (status == 0)
+                       status = urb->status;
+       }
+
+       if (done) {
+               /* set status */
+               urb->status = status;
+               urb->actual_length = qh->offset;
+               musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT);
+
+       } else if (!(tx_csr & MUSB_TXCSR_DMAENAB)) {
+               /* WARN_ON(!buf); */
+
+               /* REVISIT:  some docs say that when hw_ep->tx_double_buffered,
+                * (and presumably, fifo is not half-full) we should write TWO
+                * packets before updating TXCSR ... other docs disagree ...
+                */
+               /* PIO:  start next packet in this URB */
+               wLength = min(qh->maxpacket, (u16) wLength);
+               musb_write_fifo(hw_ep, wLength, buf);
+               qh->segsize = wLength;
+
+               musb_ep_select(mbase, epnum);
+               musb_writew(epio, MUSB_TXCSR,
+                               MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
+       } else
+               DBG(1, "not complete, but dma enabled?\n");
+
+finish:
+       return;
+}
+
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+
+/* Host side RX (IN) using Mentor DMA works as follows:
+       submit_urb ->
+               - if queue was empty, ProgramEndpoint
+               - first IN token is sent out (by setting ReqPkt)
+       LinuxIsr -> RxReady()
+       /\      => first packet is received
+       |       - Set in mode 0 (DmaEnab, ~ReqPkt)
+       |               -> DMA Isr (transfer complete) -> RxReady()
+       |                   - Ack receive (~RxPktRdy), turn off DMA (~DmaEnab)
+       |                   - if urb not complete, send next IN token (ReqPkt)
+       |                          |            else complete urb.
+       |                          |
+       ---------------------------
+ *
+ * Nuances of mode 1:
+ *     For short packets, no ack (+RxPktRdy) is sent automatically
+ *     (even if AutoClear is ON)
+ *     For full packets, ack (~RxPktRdy) and next IN token (+ReqPkt) is sent
+ *     automatically => major problem, as collecting the next packet becomes
+ *     difficult. Hence mode 1 is not used.
+ *
+ * REVISIT
+ *     All we care about at this driver level is that
+ *       (a) all URBs terminate with REQPKT cleared and fifo(s) empty;
+ *       (b) termination conditions are: short RX, or buffer full;
+ *       (c) fault modes include
+ *           - iff URB_SHORT_NOT_OK, short RX status is -EREMOTEIO.
+ *             (and that endpoint's dma queue stops immediately)
+ *           - overflow (full, PLUS more bytes in the terminal packet)
+ *
+ *     So for example, usb-storage sets URB_SHORT_NOT_OK, and would
+ *     thus be a great candidate for using mode 1 ... for all but the
+ *     last packet of one URB's transfer.
+ */
+
+#endif
+
+/*
+ * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso,
+ * and high-bandwidth IN transfer cases.
+ */
+void musb_host_rx(struct musb *musb, u8 epnum)
+{
+       struct urb              *urb;
+       struct musb_hw_ep       *hw_ep = musb->endpoints + epnum;
+       void __iomem            *epio = hw_ep->regs;
+       struct musb_qh          *qh = hw_ep->in_qh;
+       size_t                  xfer_len;
+       void __iomem            *mbase = musb->mregs;
+       int                     pipe;
+       u16                     rx_csr, val;
+       bool                    iso_err = false;
+       bool                    done = false;
+       u32                     status;
+       struct dma_channel      *dma;
+
+       musb_ep_select(mbase, epnum);
+
+       urb = next_urb(qh);
+       dma = is_dma_capable() ? hw_ep->rx_channel : NULL;
+       status = 0;
+       xfer_len = 0;
+
+       rx_csr = musb_readw(epio, MUSB_RXCSR);
+       val = rx_csr;
+
+       if (unlikely(!urb)) {
+               /* REVISIT -- THIS SHOULD NEVER HAPPEN ... but, at least
+                * usbtest #11 (unlinks) triggers it regularly, sometimes
+                * with fifo full.  (Only with DMA??)
+                */
+               DBG(3, "BOGUS RX%d ready, csr %04x, count %d\n", epnum, val,
+                       musb_readw(epio, MUSB_RXCOUNT));
+               musb_h_flush_rxfifo(hw_ep, MUSB_RXCSR_CLRDATATOG);
+               return;
+       }
+
+       pipe = urb->pipe;
+
+       DBG(5, "<== hw %d rxcsr %04x, urb actual %d (+dma %zu)\n",
+               epnum, rx_csr, urb->actual_length,
+               dma ? dma->actual_len : 0);
+
+       /* check for errors, concurrent stall & unlink is not really
+        * handled yet! */
+       if (rx_csr & MUSB_RXCSR_H_RXSTALL) {
+               DBG(3, "RX end %d STALL\n", epnum);
+
+               /* stall; record URB status */
+               status = -EPIPE;
+
+       } else if (rx_csr & MUSB_RXCSR_H_ERROR) {
+               DBG(3, "end %d RX proto error\n", epnum);
+
+               status = -EPROTO;
+               musb_writeb(epio, MUSB_RXINTERVAL, 0);
+
+       } else if (rx_csr & MUSB_RXCSR_DATAERROR) {
+
+               if (USB_ENDPOINT_XFER_ISOC != qh->type) {
+                       /* NOTE this code path would be a good place to PAUSE a
+                        * transfer, if there's some other (nonperiodic) rx urb
+                        * that could use this fifo.  (dma complicates it...)
+                        *
+                        * if (bulk && qh->ring.next != &musb->in_bulk), then
+                        * we have a candidate... NAKing is *NOT* an error
+                        */
+                       DBG(6, "RX end %d NAK timeout\n", epnum);
+                       musb_ep_select(mbase, epnum);
+                       musb_writew(epio, MUSB_RXCSR,
+                                       MUSB_RXCSR_H_WZC_BITS
+                                       | MUSB_RXCSR_H_REQPKT);
+
+                       goto finish;
+               } else {
+                       DBG(4, "RX end %d ISO data error\n", epnum);
+                       /* packet error reported later */
+                       iso_err = true;
+               }
+       }
+
+       /* faults abort the transfer */
+       if (status) {
+               /* clean up dma and collect transfer count */
+               if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+                       dma->status = MUSB_DMA_STATUS_CORE_ABORT;
+                       (void) musb->dma_controller->channel_abort(dma);
+                       xfer_len = dma->actual_len;
+               }
+               musb_h_flush_rxfifo(hw_ep, MUSB_RXCSR_CLRDATATOG);
+               musb_writeb(epio, MUSB_RXINTERVAL, 0);
+               done = true;
+               goto finish;
+       }
+
+       if (unlikely(dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY)) {
+               /* SHOULD NEVER HAPPEN ... but at least DaVinci has done it */
+               ERR("RX%d dma busy, csr %04x\n", epnum, rx_csr);
+               goto finish;
+       }
+
+       /* thorough shutdown for now ... given more precise fault handling
+        * and better queueing support, we might keep a DMA pipeline going
+        * while processing this irq for earlier completions.
+        */
+
+       /* FIXME this is _way_ too much in-line logic for Mentor DMA */
+
+#ifndef CONFIG_USB_INVENTRA_DMA
+       if (rx_csr & MUSB_RXCSR_H_REQPKT)  {
+               /* REVISIT this happened for a while on some short reads...
+                * the cleanup still needs investigation... looks bad...
+                * and also duplicates dma cleanup code above ... plus,
+                * shouldn't this be the "half full" double buffer case?
+                */
+               if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+                       dma->status = MUSB_DMA_STATUS_CORE_ABORT;
+                       (void) musb->dma_controller->channel_abort(dma);
+                       xfer_len = dma->actual_len;
+                       done = true;
+               }
+
+               DBG(2, "RXCSR%d %04x, reqpkt, len %zu%s\n", epnum, rx_csr,
+                               xfer_len, dma ? ", dma" : "");
+               rx_csr &= ~MUSB_RXCSR_H_REQPKT;
+
+               musb_ep_select(mbase, epnum);
+               musb_writew(epio, MUSB_RXCSR,
+                               MUSB_RXCSR_H_WZC_BITS | rx_csr);
+       }
+#endif
+       if (dma && (rx_csr & MUSB_RXCSR_DMAENAB)) {
+               xfer_len = dma->actual_len;
+
+               val &= ~(MUSB_RXCSR_DMAENAB
+                       | MUSB_RXCSR_H_AUTOREQ
+                       | MUSB_RXCSR_AUTOCLEAR
+                       | MUSB_RXCSR_RXPKTRDY);
+               musb_writew(hw_ep->regs, MUSB_RXCSR, val);
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+               /* done if urb buffer is full or short packet is recd */
+               done = (urb->actual_length + xfer_len >=
+                               urb->transfer_buffer_length
+                       || dma->actual_len < qh->maxpacket);
+
+               /* send IN token for next packet, without AUTOREQ */
+               if (!done) {
+                       val |= MUSB_RXCSR_H_REQPKT;
+                       musb_writew(epio, MUSB_RXCSR,
+                               MUSB_RXCSR_H_WZC_BITS | val);
+               }
+
+               DBG(4, "ep %d dma %s, rxcsr %04x, rxcount %d\n", epnum,
+                       done ? "off" : "reset",
+                       musb_readw(epio, MUSB_RXCSR),
+                       musb_readw(epio, MUSB_RXCOUNT));
+#else
+               done = true;
+#endif
+       } else if (urb->status == -EINPROGRESS) {
+               /* if no errors, be sure a packet is ready for unloading */
+               if (unlikely(!(rx_csr & MUSB_RXCSR_RXPKTRDY))) {
+                       status = -EPROTO;
+                       ERR("Rx interrupt with no errors or packet!\n");
+
+                       /* FIXME this is another "SHOULD NEVER HAPPEN" */
+
+/* SCRUB (RX) */
+                       /* do the proper sequence to abort the transfer */
+                       musb_ep_select(mbase, epnum);
+                       val &= ~MUSB_RXCSR_H_REQPKT;
+                       musb_writew(epio, MUSB_RXCSR, val);
+                       goto finish;
+               }
+
+               /* we are expecting IN packets */
+#ifdef CONFIG_USB_INVENTRA_DMA
+               if (dma) {
+                       struct dma_controller   *c;
+                       u16                     rx_count;
+                       int                     ret;
+
+                       rx_count = musb_readw(epio, MUSB_RXCOUNT);
+
+                       DBG(2, "RX%d count %d, buffer 0x%x len %d/%d\n",
+                                       epnum, rx_count,
+                                       urb->transfer_dma
+                                               + urb->actual_length,
+                                       qh->offset,
+                                       urb->transfer_buffer_length);
+
+                       c = musb->dma_controller;
+
+                       dma->desired_mode = 0;
+#ifdef USE_MODE1
+                       /* because of the issue below, mode 1 will
+                        * only rarely behave with correct semantics.
+                        */
+                       if ((urb->transfer_flags &
+                                               URB_SHORT_NOT_OK)
+                               && (urb->transfer_buffer_length -
+                                               urb->actual_length)
+                                       > qh->maxpacket)
+                               dma->desired_mode = 1;
+#endif
+
+/* Disadvantage of using mode 1:
+ *     It's basically usable only for mass storage class; essentially all
+ *     other protocols also terminate transfers on short packets.
+ *
+ * Details:
+ *     An extra IN token is sent at the end of the transfer (due to AUTOREQ)
+ *     If you try to use mode 1 for (transfer_buffer_length - 512), and try
+ *     to use the extra IN token to grab the last packet using mode 0, then
+ *     the problem is that you cannot be sure when the device will send the
+ *     last packet and RxPktRdy set. Sometimes the packet is recd too soon
+ *     such that it gets lost when RxCSR is re-set at the end of the mode 1
+ *     transfer, while sometimes it is recd just a little late so that if you
+ *     try to configure for mode 0 soon after the mode 1 transfer is
+ *     completed, you will find rxcount 0. Okay, so you might think why not
+ *     wait for an interrupt when the pkt is recd. Well, you won't get any!
+ */
+
+                       val = musb_readw(epio, MUSB_RXCSR);
+                       val &= ~MUSB_RXCSR_H_REQPKT;
+
+                       if (dma->desired_mode == 0)
+                               val &= ~MUSB_RXCSR_H_AUTOREQ;
+                       else
+                               val |= MUSB_RXCSR_H_AUTOREQ;
+                       val |= MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB;
+
+                       musb_writew(epio, MUSB_RXCSR,
+                               MUSB_RXCSR_H_WZC_BITS | val);
+
+                       /* REVISIT if when actual_length != 0,
+                        * transfer_buffer_length needs to be
+                        * adjusted first...
+                        */
+                       ret = c->channel_program(
+                               dma, qh->maxpacket,
+                               dma->desired_mode,
+                               urb->transfer_dma
+                                       + urb->actual_length,
+                               (dma->desired_mode == 0)
+                                       ? rx_count
+                                       : urb->transfer_buffer_length);
+
+                       if (!ret) {
+                               c->channel_release(dma);
+                               hw_ep->rx_channel = NULL;
+                               dma = NULL;
+                               /* REVISIT reset CSR */
+                       }
+               }
+#endif /* Mentor DMA */
+
+               if (!dma) {
+                       done = musb_host_packet_rx(musb, urb,
+                                       epnum, iso_err);
+                       DBG(6, "read %spacket\n", done ? "last " : "");
+               }
+       }
+
+       if (dma && usb_pipeisoc(pipe)) {
+               struct usb_iso_packet_descriptor        *d;
+               int                                     iso_stat = status;
+
+               d = urb->iso_frame_desc + qh->iso_idx;
+               d->actual_length += xfer_len;
+               if (iso_err) {
+                       iso_stat = -EILSEQ;
+                       urb->error_count++;
+               }
+               d->status = iso_stat;
+       }
+
+finish:
+       urb->actual_length += xfer_len;
+       qh->offset += xfer_len;
+       if (done) {
+               if (urb->status == -EINPROGRESS)
+                       urb->status = status;
+               musb_advance_schedule(musb, urb, hw_ep, USB_DIR_IN);
+       }
+}
+
+/* schedule nodes correspond to peripheral endpoints, like an OHCI QH.
+ * the software schedule associates multiple such nodes with a given
+ * host side hardware endpoint + direction; scheduling may activate
+ * that hardware endpoint.
+ */
+static int musb_schedule(
+       struct musb             *musb,
+       struct musb_qh          *qh,
+       int                     is_in)
+{
+       int                     idle;
+       int                     best_diff;
+       int                     best_end, epnum;
+       struct musb_hw_ep       *hw_ep = NULL;
+       struct list_head        *head = NULL;
+
+       /* use fixed hardware for control and bulk */
+       switch (qh->type) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               head = &musb->control;
+               hw_ep = musb->control_ep;
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               hw_ep = musb->bulk_ep;
+               if (is_in)
+                       head = &musb->in_bulk;
+               else
+                       head = &musb->out_bulk;
+               break;
+       }
+       if (head) {
+               idle = list_empty(head);
+               list_add_tail(&qh->ring, head);
+               goto success;
+       }
+
+       /* else, periodic transfers get muxed to other endpoints */
+
+       /* FIXME this doesn't consider direction, so it can only
+        * work for one half of the endpoint hardware, and assumes
+        * the previous cases handled all non-shared endpoints...
+        */
+
+       /* we know this qh hasn't been scheduled, so all we need to do
+        * is choose which hardware endpoint to put it on ...
+        *
+        * REVISIT what we really want here is a regular schedule tree
+        * like e.g. OHCI uses, but for now musb->periodic is just an
+        * array of the _single_ logical endpoint associated with a
+        * given physical one (identity mapping logical->physical).
+        *
+        * that simplistic approach makes TT scheduling a lot simpler;
+        * there is none, and thus none of its complexity...
+        */
+       best_diff = 4096;
+       best_end = -1;
+
+       for (epnum = 1; epnum < musb->nr_endpoints; epnum++) {
+               int     diff;
+
+               if (musb->periodic[epnum])
+                       continue;
+               hw_ep = &musb->endpoints[epnum];
+               if (hw_ep == musb->bulk_ep)
+                       continue;
+
+               if (is_in)
+                       diff = hw_ep->max_packet_sz_rx - qh->maxpacket;
+               else
+                       diff = hw_ep->max_packet_sz_tx - qh->maxpacket;
+
+               if (diff > 0 && best_diff > diff) {
+                       best_diff = diff;
+                       best_end = epnum;
+               }
+       }
+       if (best_end < 0)
+               return -ENOSPC;
+
+       idle = 1;
+       hw_ep = musb->endpoints + best_end;
+       musb->periodic[best_end] = qh;
+       DBG(4, "qh %p periodic slot %d\n", qh, best_end);
+success:
+       qh->hw_ep = hw_ep;
+       qh->hep->hcpriv = qh;
+       if (idle)
+               musb_start_urb(musb, is_in, qh);
+       return 0;
+}
+
+static int musb_urb_enqueue(
+       struct usb_hcd                  *hcd,
+       struct urb                      *urb,
+       gfp_t                           mem_flags)
+{
+       unsigned long                   flags;
+       struct musb                     *musb = hcd_to_musb(hcd);
+       struct usb_host_endpoint        *hep = urb->ep;
+       struct musb_qh                  *qh = hep->hcpriv;
+       struct usb_endpoint_descriptor  *epd = &hep->desc;
+       int                             ret;
+       unsigned                        type_reg;
+       unsigned                        interval;
+
+       /* host role must be active */
+       if (!is_host_active(musb) || !musb->is_active)
+               return -ENODEV;
+
+       spin_lock_irqsave(&musb->lock, flags);
+       ret = usb_hcd_link_urb_to_ep(hcd, urb);
+       spin_unlock_irqrestore(&musb->lock, flags);
+       if (ret)
+               return ret;
+
+       /* DMA mapping was already done, if needed, and this urb is on
+        * hep->urb_list ... so there's little to do unless hep wasn't
+        * yet scheduled onto a live qh.
+        *
+        * REVISIT best to keep hep->hcpriv valid until the endpoint gets
+        * disabled, testing for empty qh->ring and avoiding qh setup costs
+        * except for the first urb queued after a config change.
+        */
+       if (qh) {
+               urb->hcpriv = qh;
+               return 0;
+       }
+
+       /* Allocate and initialize qh, minimizing the work done each time
+        * hw_ep gets reprogrammed, or with irqs blocked.  Then schedule it.
+        *
+        * REVISIT consider a dedicated qh kmem_cache, so it's harder
+        * for bugs in other kernel code to break this driver...
+        */
+       qh = kzalloc(sizeof *qh, mem_flags);
+       if (!qh) {
+               usb_hcd_unlink_urb_from_ep(hcd, urb);
+               return -ENOMEM;
+       }
+
+       qh->hep = hep;
+       qh->dev = urb->dev;
+       INIT_LIST_HEAD(&qh->ring);
+       qh->is_ready = 1;
+
+       qh->maxpacket = le16_to_cpu(epd->wMaxPacketSize);
+
+       /* no high bandwidth support yet */
+       if (qh->maxpacket & ~0x7ff) {
+               ret = -EMSGSIZE;
+               goto done;
+       }
+
+       qh->epnum = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+       qh->type = epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+
+       /* NOTE: urb->dev->devnum is wrong during SET_ADDRESS */
+       qh->addr_reg = (u8) usb_pipedevice(urb->pipe);
+
+       /* precompute rxtype/txtype/type0 register */
+       type_reg = (qh->type << 4) | qh->epnum;
+       switch (urb->dev->speed) {
+       case USB_SPEED_LOW:
+               type_reg |= 0xc0;
+               break;
+       case USB_SPEED_FULL:
+               type_reg |= 0x80;
+               break;
+       default:
+               type_reg |= 0x40;
+       }
+       qh->type_reg = type_reg;
+
+       /* precompute rxinterval/txinterval register */
+       interval = min((u8)16, epd->bInterval); /* log encoding */
+       switch (qh->type) {
+       case USB_ENDPOINT_XFER_INT:
+               /* fullspeed uses linear encoding */
+               if (USB_SPEED_FULL == urb->dev->speed) {
+                       interval = epd->bInterval;
+                       if (!interval)
+                               interval = 1;
+               }
+               /* FALLTHROUGH */
+       case USB_ENDPOINT_XFER_ISOC:
+               /* iso always uses log encoding */
+               break;
+       default:
+               /* REVISIT we actually want to use NAK limits, hinting to the
+                * transfer scheduling logic to try some other qh, e.g. try
+                * for 2 msec first:
+                *
+                * interval = (USB_SPEED_HIGH == urb->dev->speed) ? 16 : 2;
+                *
+                * The downside of disabling this is that transfer scheduling
+                * gets VERY unfair for nonperiodic transfers; a misbehaving
+                * peripheral could make that hurt.  Or for reads, one that's
+                * perfectly normal:  network and other drivers keep reads
+                * posted at all times, having one pending for a week should
+                * be perfectly safe.
+                *
+                * The upside of disabling it is avoidng transfer scheduling
+                * code to put this aside for while.
+                */
+               interval = 0;
+       }
+       qh->intv_reg = interval;
+
+       /* precompute addressing for external hub/tt ports */
+       if (musb->is_multipoint) {
+               struct usb_device       *parent = urb->dev->parent;
+
+               if (parent != hcd->self.root_hub) {
+                       qh->h_addr_reg = (u8) parent->devnum;
+
+                       /* set up tt info if needed */
+                       if (urb->dev->tt) {
+                               qh->h_port_reg = (u8) urb->dev->ttport;
+                               qh->h_addr_reg |= 0x80;
+                       }
+               }
+       }
+
+       /* invariant: hep->hcpriv is null OR the qh that's already scheduled.
+        * until we get real dma queues (with an entry for each urb/buffer),
+        * we only have work to do in the former case.
+        */
+       spin_lock_irqsave(&musb->lock, flags);
+       if (hep->hcpriv) {
+               /* some concurrent activity submitted another urb to hep...
+                * odd, rare, error prone, but legal.
+                */
+               kfree(qh);
+               ret = 0;
+       } else
+               ret = musb_schedule(musb, qh,
+                               epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK);
+
+       if (ret == 0) {
+               urb->hcpriv = qh;
+               /* FIXME set urb->start_frame for iso/intr, it's tested in
+                * musb_start_urb(), but otherwise only konicawc cares ...
+                */
+       }
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+done:
+       if (ret != 0) {
+               usb_hcd_unlink_urb_from_ep(hcd, urb);
+               kfree(qh);
+       }
+       return ret;
+}
+
+
+/*
+ * abort a transfer that's at the head of a hardware queue.
+ * called with controller locked, irqs blocked
+ * that hardware queue advances to the next transfer, unless prevented
+ */
+static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in)
+{
+       struct musb_hw_ep       *ep = qh->hw_ep;
+       void __iomem            *epio = ep->regs;
+       unsigned                hw_end = ep->epnum;
+       void __iomem            *regs = ep->musb->mregs;
+       u16                     csr;
+       int                     status = 0;
+
+       musb_ep_select(regs, hw_end);
+
+       if (is_dma_capable()) {
+               struct dma_channel      *dma;
+
+               dma = is_in ? ep->rx_channel : ep->tx_channel;
+               if (dma) {
+                       status = ep->musb->dma_controller->channel_abort(dma);
+                       DBG(status ? 1 : 3,
+                               "abort %cX%d DMA for urb %p --> %d\n",
+                               is_in ? 'R' : 'T', ep->epnum,
+                               urb, status);
+                       urb->actual_length += dma->actual_len;
+               }
+       }
+
+       /* turn off DMA requests, discard state, stop polling ... */
+       if (is_in) {
+               /* giveback saves bulk toggle */
+               csr = musb_h_flush_rxfifo(ep, 0);
+
+               /* REVISIT we still get an irq; should likely clear the
+                * endpoint's irq status here to avoid bogus irqs.
+                * clearing that status is platform-specific...
+                */
+       } else {
+               musb_h_tx_flush_fifo(ep);
+               csr = musb_readw(epio, MUSB_TXCSR);
+               csr &= ~(MUSB_TXCSR_AUTOSET
+                       | MUSB_TXCSR_DMAENAB
+                       | MUSB_TXCSR_H_RXSTALL
+                       | MUSB_TXCSR_H_NAKTIMEOUT
+                       | MUSB_TXCSR_H_ERROR
+                       | MUSB_TXCSR_TXPKTRDY);
+               musb_writew(epio, MUSB_TXCSR, csr);
+               /* REVISIT may need to clear FLUSHFIFO ... */
+               musb_writew(epio, MUSB_TXCSR, csr);
+               /* flush cpu writebuffer */
+               csr = musb_readw(epio, MUSB_TXCSR);
+       }
+       if (status == 0)
+               musb_advance_schedule(ep->musb, urb, ep, is_in);
+       return status;
+}
+
+static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+{
+       struct musb             *musb = hcd_to_musb(hcd);
+       struct musb_qh          *qh;
+       struct list_head        *sched;
+       unsigned long           flags;
+       int                     ret;
+
+       DBG(4, "urb=%p, dev%d ep%d%s\n", urb,
+                       usb_pipedevice(urb->pipe),
+                       usb_pipeendpoint(urb->pipe),
+                       usb_pipein(urb->pipe) ? "in" : "out");
+
+       spin_lock_irqsave(&musb->lock, flags);
+       ret = usb_hcd_check_unlink_urb(hcd, urb, status);
+       if (ret)
+               goto done;
+
+       qh = urb->hcpriv;
+       if (!qh)
+               goto done;
+
+       /* Any URB not actively programmed into endpoint hardware can be
+        * immediately given back.  Such an URB must be at the head of its
+        * endpoint queue, unless someday we get real DMA queues.  And even
+        * then, it might not be known to the hardware...
+        *
+        * Otherwise abort current transfer, pending dma, etc.; urb->status
+        * has already been updated.  This is a synchronous abort; it'd be
+        * OK to hold off until after some IRQ, though.
+        */
+       if (!qh->is_ready || urb->urb_list.prev != &qh->hep->urb_list)
+               ret = -EINPROGRESS;
+       else {
+               switch (qh->type) {
+               case USB_ENDPOINT_XFER_CONTROL:
+                       sched = &musb->control;
+                       break;
+               case USB_ENDPOINT_XFER_BULK:
+                       if (usb_pipein(urb->pipe))
+                               sched = &musb->in_bulk;
+                       else
+                               sched = &musb->out_bulk;
+                       break;
+               default:
+                       /* REVISIT when we get a schedule tree, periodic
+                        * transfers won't always be at the head of a
+                        * singleton queue...
+                        */
+                       sched = NULL;
+                       break;
+               }
+       }
+
+       /* NOTE:  qh is invalid unless !list_empty(&hep->urb_list) */
+       if (ret < 0 || (sched && qh != first_qh(sched))) {
+               int     ready = qh->is_ready;
+
+               ret = 0;
+               qh->is_ready = 0;
+               __musb_giveback(musb, urb, 0);
+               qh->is_ready = ready;
+       } else
+               ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
+done:
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return ret;
+}
+
+/* disable an endpoint */
+static void
+musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
+{
+       u8                      epnum = hep->desc.bEndpointAddress;
+       unsigned long           flags;
+       struct musb             *musb = hcd_to_musb(hcd);
+       u8                      is_in = epnum & USB_DIR_IN;
+       struct musb_qh          *qh = hep->hcpriv;
+       struct urb              *urb, *tmp;
+       struct list_head        *sched;
+
+       if (!qh)
+               return;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       switch (qh->type) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               sched = &musb->control;
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               if (is_in)
+                       sched = &musb->in_bulk;
+               else
+                       sched = &musb->out_bulk;
+               break;
+       default:
+               /* REVISIT when we get a schedule tree, periodic transfers
+                * won't always be at the head of a singleton queue...
+                */
+               sched = NULL;
+               break;
+       }
+
+       /* NOTE:  qh is invalid unless !list_empty(&hep->urb_list) */
+
+       /* kick first urb off the hardware, if needed */
+       qh->is_ready = 0;
+       if (!sched || qh == first_qh(sched)) {
+               urb = next_urb(qh);
+
+               /* make software (then hardware) stop ASAP */
+               if (!urb->unlinked)
+                       urb->status = -ESHUTDOWN;
+
+               /* cleanup */
+               musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
+       } else
+               urb = NULL;
+
+       /* then just nuke all the others */
+       list_for_each_entry_safe_from(urb, tmp, &hep->urb_list, urb_list)
+               musb_giveback(qh, urb, -ESHUTDOWN);
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static int musb_h_get_frame_number(struct usb_hcd *hcd)
+{
+       struct musb     *musb = hcd_to_musb(hcd);
+
+       return musb_readw(musb->mregs, MUSB_FRAME);
+}
+
+static int musb_h_start(struct usb_hcd *hcd)
+{
+       struct musb     *musb = hcd_to_musb(hcd);
+
+       /* NOTE: musb_start() is called when the hub driver turns
+        * on port power, or when (OTG) peripheral starts.
+        */
+       hcd->state = HC_STATE_RUNNING;
+       musb->port1_status = 0;
+       return 0;
+}
+
+static void musb_h_stop(struct usb_hcd *hcd)
+{
+       musb_stop(hcd_to_musb(hcd));
+       hcd->state = HC_STATE_HALT;
+}
+
+static int musb_bus_suspend(struct usb_hcd *hcd)
+{
+       struct musb     *musb = hcd_to_musb(hcd);
+
+       if (musb->xceiv.state == OTG_STATE_A_SUSPEND)
+               return 0;
+
+       if (is_host_active(musb) && musb->is_active) {
+               WARNING("trying to suspend as %s is_active=%i\n",
+                       otg_state_string(musb), musb->is_active);
+               return -EBUSY;
+       } else
+               return 0;
+}
+
+static int musb_bus_resume(struct usb_hcd *hcd)
+{
+       /* resuming child port does the work */
+       return 0;
+}
+
+const struct hc_driver musb_hc_driver = {
+       .description            = "musb-hcd",
+       .product_desc           = "MUSB HDRC host driver",
+       .hcd_priv_size          = sizeof(struct musb),
+       .flags                  = HCD_USB2 | HCD_MEMORY,
+
+       /* not using irq handler or reset hooks from usbcore, since
+        * those must be shared with peripheral code for OTG configs
+        */
+
+       .start                  = musb_h_start,
+       .stop                   = musb_h_stop,
+
+       .get_frame_number       = musb_h_get_frame_number,
+
+       .urb_enqueue            = musb_urb_enqueue,
+       .urb_dequeue            = musb_urb_dequeue,
+       .endpoint_disable       = musb_h_disable,
+
+       .hub_status_data        = musb_hub_status_data,
+       .hub_control            = musb_hub_control,
+       .bus_suspend            = musb_bus_suspend,
+       .bus_resume             = musb_bus_resume,
+       /* .start_port_reset    = NULL, */
+       /* .hub_irq_enable      = NULL, */
+};
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h
new file mode 100644 (file)
index 0000000..77bcdb9
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * MUSB OTG driver host defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _MUSB_HOST_H
+#define _MUSB_HOST_H
+
+static inline struct usb_hcd *musb_to_hcd(struct musb *musb)
+{
+       return container_of((void *) musb, struct usb_hcd, hcd_priv);
+}
+
+static inline struct musb *hcd_to_musb(struct usb_hcd *hcd)
+{
+       return (struct musb *) (hcd->hcd_priv);
+}
+
+/* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints */
+struct musb_qh {
+       struct usb_host_endpoint *hep;          /* usbcore info */
+       struct usb_device       *dev;
+       struct musb_hw_ep       *hw_ep;         /* current binding */
+
+       struct list_head        ring;           /* of musb_qh */
+       /* struct musb_qh               *next; */       /* for periodic tree */
+
+       unsigned                offset;         /* in urb->transfer_buffer */
+       unsigned                segsize;        /* current xfer fragment */
+
+       u8                      type_reg;       /* {rx,tx} type register */
+       u8                      intv_reg;       /* {rx,tx} interval register */
+       u8                      addr_reg;       /* device address register */
+       u8                      h_addr_reg;     /* hub address register */
+       u8                      h_port_reg;     /* hub port register */
+
+       u8                      is_ready;       /* safe to modify hw_ep */
+       u8                      type;           /* XFERTYPE_* */
+       u8                      epnum;
+       u16                     maxpacket;
+       u16                     frame;          /* for periodic schedule */
+       unsigned                iso_idx;        /* in urb->iso_frame_desc[] */
+};
+
+/* map from control or bulk queue head to the first qh on that ring */
+static inline struct musb_qh *first_qh(struct list_head *q)
+{
+       if (list_empty(q))
+               return NULL;
+       return list_entry(q->next, struct musb_qh, ring);
+}
+
+
+extern void musb_root_disconnect(struct musb *musb);
+
+struct usb_hcd;
+
+extern int musb_hub_status_data(struct usb_hcd *hcd, char *buf);
+extern int musb_hub_control(struct usb_hcd *hcd,
+                       u16 typeReq, u16 wValue, u16 wIndex,
+                       char *buf, u16 wLength);
+
+extern const struct hc_driver musb_hc_driver;
+
+static inline struct urb *next_urb(struct musb_qh *qh)
+{
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       struct list_head        *queue;
+
+       if (!qh)
+               return NULL;
+       queue = &qh->hep->urb_list;
+       if (list_empty(queue))
+               return NULL;
+       return list_entry(queue->next, struct urb, urb_list);
+#else
+       return NULL;
+#endif
+}
+
+#endif                         /* _MUSB_HOST_H */
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h
new file mode 100644 (file)
index 0000000..6bbedae
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * MUSB OTG driver register I/O
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_LINUX_PLATFORM_ARCH_H__
+#define __MUSB_LINUX_PLATFORM_ARCH_H__
+
+#include <linux/io.h>
+
+#ifndef        CONFIG_ARM
+static inline void readsl(const void __iomem *addr, void *buf, int len)
+       { insl((unsigned long)addr, buf, len); }
+static inline void readsw(const void __iomem *addr, void *buf, int len)
+       { insw((unsigned long)addr, buf, len); }
+static inline void readsb(const void __iomem *addr, void *buf, int len)
+       { insb((unsigned long)addr, buf, len); }
+
+static inline void writesl(const void __iomem *addr, const void *buf, int len)
+       { outsl((unsigned long)addr, buf, len); }
+static inline void writesw(const void __iomem *addr, const void *buf, int len)
+       { outsw((unsigned long)addr, buf, len); }
+static inline void writesb(const void __iomem *addr, const void *buf, int len)
+       { outsb((unsigned long)addr, buf, len); }
+
+#endif
+
+/* NOTE:  these offsets are all in bytes */
+
+static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
+       { return __raw_readw(addr + offset); }
+
+static inline u32 musb_readl(const void __iomem *addr, unsigned offset)
+       { return __raw_readl(addr + offset); }
+
+
+static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data)
+       { __raw_writew(data, addr + offset); }
+
+static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data)
+       { __raw_writel(data, addr + offset); }
+
+
+#ifdef CONFIG_USB_TUSB6010
+
+/*
+ * TUSB6010 doesn't allow 8-bit access; 16-bit access is the minimum.
+ */
+static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
+{
+       u16 tmp;
+       u8 val;
+
+       tmp = __raw_readw(addr + (offset & ~1));
+       if (offset & 1)
+               val = (tmp >> 8);
+       else
+               val = tmp & 0xff;
+
+       return val;
+}
+
+static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+{
+       u16 tmp;
+
+       tmp = __raw_readw(addr + (offset & ~1));
+       if (offset & 1)
+               tmp = (data << 8) | (tmp & 0xff);
+       else
+               tmp = (tmp & 0xff00) | data;
+
+       __raw_writew(tmp, addr + (offset & ~1));
+}
+
+#else
+
+static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
+       { return __raw_readb(addr + offset); }
+
+static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+       { __raw_writeb(data, addr + offset); }
+
+#endif /* CONFIG_USB_TUSB6010 */
+
+#endif
diff --git a/drivers/usb/musb/musb_procfs.c b/drivers/usb/musb/musb_procfs.c
new file mode 100644 (file)
index 0000000..55e6b78
--- /dev/null
@@ -0,0 +1,830 @@
+/*
+ * MUSB OTG driver debug support
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>     /* FIXME remove procfs writes */
+#include <asm/arch/hardware.h>
+
+#include "musb_core.h"
+
+#include "davinci.h"
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+
+static int dump_qh(struct musb_qh *qh, char *buf, unsigned max)
+{
+       int                             count;
+       int                             tmp;
+       struct usb_host_endpoint        *hep = qh->hep;
+       struct urb                      *urb;
+
+       count = snprintf(buf, max, "    qh %p dev%d ep%d%s max%d\n",
+                       qh, qh->dev->devnum, qh->epnum,
+                       ({ char *s; switch (qh->type) {
+                       case USB_ENDPOINT_XFER_BULK:
+                               s = "-bulk"; break;
+                       case USB_ENDPOINT_XFER_INT:
+                               s = "-int"; break;
+                       case USB_ENDPOINT_XFER_CONTROL:
+                               s = ""; break;
+                       default:
+                               s = "iso"; break;
+                       }; s; }),
+                       qh->maxpacket);
+       if (count <= 0)
+               return 0;
+       buf += count;
+       max -= count;
+
+       list_for_each_entry(urb, &hep->urb_list, urb_list) {
+               tmp = snprintf(buf, max, "\t%s urb %p %d/%d\n",
+                               usb_pipein(urb->pipe) ? "in" : "out",
+                               urb, urb->actual_length,
+                               urb->transfer_buffer_length);
+               if (tmp <= 0)
+                       break;
+               tmp = min(tmp, (int)max);
+               count += tmp;
+               buf += tmp;
+               max -= tmp;
+       }
+       return count;
+}
+
+static int
+dump_queue(struct list_head *q, char *buf, unsigned max)
+{
+       int             count = 0;
+       struct musb_qh  *qh;
+
+       list_for_each_entry(qh, q, ring) {
+               int     tmp;
+
+               tmp = dump_qh(qh, buf, max);
+               if (tmp <= 0)
+                       break;
+               tmp = min(tmp, (int)max);
+               count += tmp;
+               buf += tmp;
+               max -= tmp;
+       }
+       return count;
+}
+
+#endif /* HCD */
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+static int dump_ep(struct musb_ep *ep, char *buffer, unsigned max)
+{
+       char            *buf = buffer;
+       int             code = 0;
+       void __iomem    *regs = ep->hw_ep->regs;
+       char            *mode = "1buf";
+
+       if (ep->is_in) {
+               if (ep->hw_ep->tx_double_buffered)
+                       mode = "2buf";
+       } else {
+               if (ep->hw_ep->rx_double_buffered)
+                       mode = "2buf";
+       }
+
+       do {
+               struct usb_request      *req;
+
+               code = snprintf(buf, max,
+                               "\n%s (hw%d): %s%s, csr %04x maxp %04x\n",
+                               ep->name, ep->current_epnum,
+                               mode, ep->dma ? " dma" : "",
+                               musb_readw(regs,
+                                       (ep->is_in || !ep->current_epnum)
+                                               ? MUSB_TXCSR
+                                               : MUSB_RXCSR),
+                               musb_readw(regs, ep->is_in
+                                               ? MUSB_TXMAXP
+                                               : MUSB_RXMAXP)
+                               );
+               if (code <= 0)
+                       break;
+               code = min(code, (int) max);
+               buf += code;
+               max -= code;
+
+               if (is_cppi_enabled() && ep->current_epnum) {
+                       unsigned        cppi = ep->current_epnum - 1;
+                       void __iomem    *base = ep->musb->ctrl_base;
+                       unsigned        off1 = cppi << 2;
+                       void __iomem    *ram = base;
+                       char            tmp[16];
+
+                       if (ep->is_in) {
+                               ram += DAVINCI_TXCPPI_STATERAM_OFFSET(cppi);
+                               tmp[0] = 0;
+                       } else {
+                               ram += DAVINCI_RXCPPI_STATERAM_OFFSET(cppi);
+                               snprintf(tmp, sizeof tmp, "%d left, ",
+                                       musb_readl(base,
+                                       DAVINCI_RXCPPI_BUFCNT0_REG + off1));
+                       }
+
+                       code = snprintf(buf, max, "%cX DMA%d: %s"
+                                       "%08x %08x, %08x %08x; "
+                                       "%08x %08x %08x .. %08x\n",
+                               ep->is_in ? 'T' : 'R',
+                               ep->current_epnum - 1, tmp,
+                               musb_readl(ram, 0 * 4),
+                               musb_readl(ram, 1 * 4),
+                               musb_readl(ram, 2 * 4),
+                               musb_readl(ram, 3 * 4),
+                               musb_readl(ram, 4 * 4),
+                               musb_readl(ram, 5 * 4),
+                               musb_readl(ram, 6 * 4),
+                               musb_readl(ram, 7 * 4));
+                       if (code <= 0)
+                               break;
+                       code = min(code, (int) max);
+                       buf += code;
+                       max -= code;
+               }
+
+               if (list_empty(&ep->req_list)) {
+                       code = snprintf(buf, max, "\t(queue empty)\n");
+                       if (code <= 0)
+                               break;
+                       code = min(code, (int) max);
+                       buf += code;
+                       max -= code;
+                       break;
+               }
+               list_for_each_entry(req, &ep->req_list, list) {
+                       code = snprintf(buf, max, "\treq %p, %s%s%d/%d\n",
+                                       req,
+                                       req->zero ? "zero, " : "",
+                                       req->short_not_ok ? "!short, " : "",
+                                       req->actual, req->length);
+                       if (code <= 0)
+                               break;
+                       code = min(code, (int) max);
+                       buf += code;
+                       max -= code;
+               }
+       } while (0);
+       return buf - buffer;
+}
+#endif
+
+static int
+dump_end_info(struct musb *musb, u8 epnum, char *aBuffer, unsigned max)
+{
+       int                     code = 0;
+       char                    *buf = aBuffer;
+       struct musb_hw_ep       *hw_ep = &musb->endpoints[epnum];
+
+       do {
+               musb_ep_select(musb->mregs, epnum);
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+               if (is_host_active(musb)) {
+                       int             dump_rx, dump_tx;
+                       void __iomem    *regs = hw_ep->regs;
+
+                       /* TEMPORARY (!) until we have a real periodic
+                        * schedule tree ...
+                        */
+                       if (!epnum) {
+                               /* control is shared, uses RX queue
+                                * but (mostly) shadowed tx registers
+                                */
+                               dump_tx = !list_empty(&musb->control);
+                               dump_rx = 0;
+                       } else if (hw_ep == musb->bulk_ep) {
+                               dump_tx = !list_empty(&musb->out_bulk);
+                               dump_rx = !list_empty(&musb->in_bulk);
+                       } else if (musb->periodic[epnum]) {
+                               struct usb_host_endpoint        *hep;
+
+                               hep = musb->periodic[epnum]->hep;
+                               dump_rx = hep->desc.bEndpointAddress
+                                               & USB_ENDPOINT_DIR_MASK;
+                               dump_tx = !dump_rx;
+                       } else
+                               break;
+                       /* END TEMPORARY */
+
+
+                       if (dump_rx) {
+                               code = snprintf(buf, max,
+                                       "\nRX%d: %s rxcsr %04x interval %02x "
+                                       "max %04x type %02x; "
+                                       "dev %d hub %d port %d"
+                                       "\n",
+                                       epnum,
+                                       hw_ep->rx_double_buffered
+                                               ? "2buf" : "1buf",
+                                       musb_readw(regs, MUSB_RXCSR),
+                                       musb_readb(regs, MUSB_RXINTERVAL),
+                                       musb_readw(regs, MUSB_RXMAXP),
+                                       musb_readb(regs, MUSB_RXTYPE),
+                                       /* FIXME:  assumes multipoint */
+                                       musb_readb(musb->mregs,
+                                               MUSB_BUSCTL_OFFSET(epnum,
+                                               MUSB_RXFUNCADDR)),
+                                       musb_readb(musb->mregs,
+                                               MUSB_BUSCTL_OFFSET(epnum,
+                                               MUSB_RXHUBADDR)),
+                                       musb_readb(musb->mregs,
+                                               MUSB_BUSCTL_OFFSET(epnum,
+                                               MUSB_RXHUBPORT))
+                                       );
+                               if (code <= 0)
+                                       break;
+                               code = min(code, (int) max);
+                               buf += code;
+                               max -= code;
+
+                               if (is_cppi_enabled()
+                                               && epnum
+                                               && hw_ep->rx_channel) {
+                                       unsigned        cppi = epnum - 1;
+                                       unsigned        off1 = cppi << 2;
+                                       void __iomem    *base;
+                                       void __iomem    *ram;
+                                       char            tmp[16];
+
+                                       base = musb->ctrl_base;
+                                       ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
+                                                       cppi) + base;
+                                       snprintf(tmp, sizeof tmp, "%d left, ",
+                                               musb_readl(base,
+                                               DAVINCI_RXCPPI_BUFCNT0_REG
+                                                               + off1));
+
+                                       code = snprintf(buf, max,
+                                               "    rx dma%d: %s"
+                                               "%08x %08x, %08x %08x; "
+                                               "%08x %08x %08x .. %08x\n",
+                                               cppi, tmp,
+                                               musb_readl(ram, 0 * 4),
+                                               musb_readl(ram, 1 * 4),
+                                               musb_readl(ram, 2 * 4),
+                                               musb_readl(ram, 3 * 4),
+                                               musb_readl(ram, 4 * 4),
+                                               musb_readl(ram, 5 * 4),
+                                               musb_readl(ram, 6 * 4),
+                                               musb_readl(ram, 7 * 4));
+                                       if (code <= 0)
+                                               break;
+                                       code = min(code, (int) max);
+                                       buf += code;
+                                       max -= code;
+                               }
+
+                               if (hw_ep == musb->bulk_ep
+                                               && !list_empty(
+                                                       &musb->in_bulk)) {
+                                       code = dump_queue(&musb->in_bulk,
+                                                       buf, max);
+                                       if (code <= 0)
+                                               break;
+                                       code = min(code, (int) max);
+                                       buf += code;
+                                       max -= code;
+                               } else if (musb->periodic[epnum]) {
+                                       code = dump_qh(musb->periodic[epnum],
+                                                       buf, max);
+                                       if (code <= 0)
+                                               break;
+                                       code = min(code, (int) max);
+                                       buf += code;
+                                       max -= code;
+                               }
+                       }
+
+                       if (dump_tx) {
+                               code = snprintf(buf, max,
+                                       "\nTX%d: %s txcsr %04x interval %02x "
+                                       "max %04x type %02x; "
+                                       "dev %d hub %d port %d"
+                                       "\n",
+                                       epnum,
+                                       hw_ep->tx_double_buffered
+                                               ? "2buf" : "1buf",
+                                       musb_readw(regs, MUSB_TXCSR),
+                                       musb_readb(regs, MUSB_TXINTERVAL),
+                                       musb_readw(regs, MUSB_TXMAXP),
+                                       musb_readb(regs, MUSB_TXTYPE),
+                                       /* FIXME:  assumes multipoint */
+                                       musb_readb(musb->mregs,
+                                               MUSB_BUSCTL_OFFSET(epnum,
+                                               MUSB_TXFUNCADDR)),
+                                       musb_readb(musb->mregs,
+                                               MUSB_BUSCTL_OFFSET(epnum,
+                                               MUSB_TXHUBADDR)),
+                                       musb_readb(musb->mregs,
+                                               MUSB_BUSCTL_OFFSET(epnum,
+                                               MUSB_TXHUBPORT))
+                                       );
+                               if (code <= 0)
+                                       break;
+                               code = min(code, (int) max);
+                               buf += code;
+                               max -= code;
+
+                               if (is_cppi_enabled()
+                                               && epnum
+                                               && hw_ep->tx_channel) {
+                                       unsigned        cppi = epnum - 1;
+                                       void __iomem    *base;
+                                       void __iomem    *ram;
+
+                                       base = musb->ctrl_base;
+                                       ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
+                                                       cppi) + base;
+                                       code = snprintf(buf, max,
+                                               "    tx dma%d: "
+                                               "%08x %08x, %08x %08x; "
+                                               "%08x %08x %08x .. %08x\n",
+                                               cppi,
+                                               musb_readl(ram, 0 * 4),
+                                               musb_readl(ram, 1 * 4),
+                                               musb_readl(ram, 2 * 4),
+                                               musb_readl(ram, 3 * 4),
+                                               musb_readl(ram, 4 * 4),
+                                               musb_readl(ram, 5 * 4),
+                                               musb_readl(ram, 6 * 4),
+                                               musb_readl(ram, 7 * 4));
+                                       if (code <= 0)
+                                               break;
+                                       code = min(code, (int) max);
+                                       buf += code;
+                                       max -= code;
+                               }
+
+                               if (hw_ep == musb->control_ep
+                                               && !list_empty(
+                                                       &musb->control)) {
+                                       code = dump_queue(&musb->control,
+                                                       buf, max);
+                                       if (code <= 0)
+                                               break;
+                                       code = min(code, (int) max);
+                                       buf += code;
+                                       max -= code;
+                               } else if (hw_ep == musb->bulk_ep
+                                               && !list_empty(
+                                                       &musb->out_bulk)) {
+                                       code = dump_queue(&musb->out_bulk,
+                                                       buf, max);
+                                       if (code <= 0)
+                                               break;
+                                       code = min(code, (int) max);
+                                       buf += code;
+                                       max -= code;
+                               } else if (musb->periodic[epnum]) {
+                                       code = dump_qh(musb->periodic[epnum],
+                                                       buf, max);
+                                       if (code <= 0)
+                                               break;
+                                       code = min(code, (int) max);
+                                       buf += code;
+                                       max -= code;
+                               }
+                       }
+               }
+#endif
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+               if (is_peripheral_active(musb)) {
+                       code = 0;
+
+                       if (hw_ep->ep_in.desc || !epnum) {
+                               code = dump_ep(&hw_ep->ep_in, buf, max);
+                               if (code <= 0)
+                                       break;
+                               code = min(code, (int) max);
+                               buf += code;
+                               max -= code;
+                       }
+                       if (hw_ep->ep_out.desc) {
+                               code = dump_ep(&hw_ep->ep_out, buf, max);
+                               if (code <= 0)
+                                       break;
+                               code = min(code, (int) max);
+                               buf += code;
+                               max -= code;
+                       }
+               }
+#endif
+       } while (0);
+
+       return buf - aBuffer;
+}
+
+/* Dump the current status and compile options.
+ * @param musb the device driver instance
+ * @param buffer where to dump the status; it must be big enough to hold the
+ * result otherwise "BAD THINGS HAPPENS(TM)".
+ */
+static int dump_header_stats(struct musb *musb, char *buffer)
+{
+       int code, count = 0;
+       const void __iomem *mbase = musb->mregs;
+
+       *buffer = 0;
+       count = sprintf(buffer, "Status: %sHDRC, Mode=%s "
+                               "(Power=%02x, DevCtl=%02x)\n",
+                       (musb->is_multipoint ? "M" : ""), MUSB_MODE(musb),
+                       musb_readb(mbase, MUSB_POWER),
+                       musb_readb(mbase, MUSB_DEVCTL));
+       if (count <= 0)
+               return 0;
+       buffer += count;
+
+       code = sprintf(buffer, "OTG state: %s; %sactive\n",
+                       otg_state_string(musb),
+                       musb->is_active ? "" : "in");
+       if (code <= 0)
+               goto done;
+       buffer += code;
+       count += code;
+
+       code = sprintf(buffer,
+                       "Options: "
+#ifdef CONFIG_MUSB_PIO_ONLY
+                       "pio"
+#elif defined(CONFIG_USB_TI_CPPI_DMA)
+                       "cppi-dma"
+#elif defined(CONFIG_USB_INVENTRA_DMA)
+                       "musb-dma"
+#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
+                       "tusb-omap-dma"
+#else
+                       "?dma?"
+#endif
+                       ", "
+#ifdef CONFIG_USB_MUSB_OTG
+                       "otg (peripheral+host)"
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+                       "peripheral"
+#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+                       "host"
+#endif
+                       ", debug=%d [eps=%d]\n",
+               debug,
+               musb->nr_endpoints);
+       if (code <= 0)
+               goto done;
+       count += code;
+       buffer += code;
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+       code = sprintf(buffer, "Peripheral address: %02x\n",
+                       musb_readb(musb->ctrl_base, MUSB_FADDR));
+       if (code <= 0)
+               goto done;
+       buffer += code;
+       count += code;
+#endif
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       code = sprintf(buffer, "Root port status: %08x\n",
+                       musb->port1_status);
+       if (code <= 0)
+               goto done;
+       buffer += code;
+       count += code;
+#endif
+
+#ifdef CONFIG_ARCH_DAVINCI
+       code = sprintf(buffer,
+                       "DaVinci: ctrl=%02x stat=%1x phy=%03x\n"
+                       "\trndis=%05x auto=%04x intsrc=%08x intmsk=%08x"
+                       "\n",
+                       musb_readl(musb->ctrl_base, DAVINCI_USB_CTRL_REG),
+                       musb_readl(musb->ctrl_base, DAVINCI_USB_STAT_REG),
+                       __raw_readl((void __force __iomem *)
+                                       IO_ADDRESS(USBPHY_CTL_PADDR)),
+                       musb_readl(musb->ctrl_base, DAVINCI_RNDIS_REG),
+                       musb_readl(musb->ctrl_base, DAVINCI_AUTOREQ_REG),
+                       musb_readl(musb->ctrl_base,
+                                       DAVINCI_USB_INT_SOURCE_REG),
+                       musb_readl(musb->ctrl_base,
+                                       DAVINCI_USB_INT_MASK_REG));
+       if (code <= 0)
+               goto done;
+       count += code;
+       buffer += code;
+#endif /* DAVINCI */
+
+#ifdef CONFIG_USB_TUSB6010
+       code = sprintf(buffer,
+                       "TUSB6010: devconf %08x, phy enable %08x drive %08x"
+                       "\n\totg %03x timer %08x"
+                       "\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x"
+                       "\n",
+                       musb_readl(musb->ctrl_base, TUSB_DEV_CONF),
+                       musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE),
+                       musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL),
+                       musb_readl(musb->ctrl_base, TUSB_DEV_OTG_STAT),
+                       musb_readl(musb->ctrl_base, TUSB_DEV_OTG_TIMER),
+                       musb_readl(musb->ctrl_base, TUSB_PRCM_CONF),
+                       musb_readl(musb->ctrl_base, TUSB_PRCM_MNGMT),
+                       musb_readl(musb->ctrl_base, TUSB_INT_SRC),
+                       musb_readl(musb->ctrl_base, TUSB_INT_MASK));
+       if (code <= 0)
+               goto done;
+       count += code;
+       buffer += code;
+#endif /* DAVINCI */
+
+       if (is_cppi_enabled() && musb->dma_controller) {
+               code = sprintf(buffer,
+                               "CPPI: txcr=%d txsrc=%01x txena=%01x; "
+                               "rxcr=%d rxsrc=%01x rxena=%01x "
+                               "\n",
+                               musb_readl(musb->ctrl_base,
+                                               DAVINCI_TXCPPI_CTRL_REG),
+                               musb_readl(musb->ctrl_base,
+                                               DAVINCI_TXCPPI_RAW_REG),
+                               musb_readl(musb->ctrl_base,
+                                               DAVINCI_TXCPPI_INTENAB_REG),
+                               musb_readl(musb->ctrl_base,
+                                               DAVINCI_RXCPPI_CTRL_REG),
+                               musb_readl(musb->ctrl_base,
+                                               DAVINCI_RXCPPI_RAW_REG),
+                               musb_readl(musb->ctrl_base,
+                                               DAVINCI_RXCPPI_INTENAB_REG));
+               if (code <= 0)
+                       goto done;
+               count += code;
+               buffer += code;
+       }
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+       if (is_peripheral_enabled(musb)) {
+               code = sprintf(buffer, "Gadget driver: %s\n",
+                               musb->gadget_driver
+                                       ? musb->gadget_driver->driver.name
+                                       : "(none)");
+               if (code <= 0)
+                       goto done;
+               count += code;
+               buffer += code;
+       }
+#endif
+
+done:
+       return count;
+}
+
+/* Write to ProcFS
+ *
+ * C soft-connect
+ * c soft-disconnect
+ * I enable HS
+ * i disable HS
+ * s stop session
+ * F force session (OTG-unfriendly)
+ * E rElinquish bus (OTG)
+ * H request host mode
+ * h cancel host request
+ * T start sending TEST_PACKET
+ * D<num> set/query the debug level
+ */
+static int musb_proc_write(struct file *file, const char __user *buffer,
+                       unsigned long count, void *data)
+{
+       char cmd;
+       u8 reg;
+       struct musb *musb = (struct musb *)data;
+       void __iomem *mbase = musb->mregs;
+
+       /* MOD_INC_USE_COUNT; */
+
+       if (unlikely(copy_from_user(&cmd, buffer, 1)))
+               return -EFAULT;
+
+       switch (cmd) {
+       case 'C':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_POWER)
+                                       | MUSB_POWER_SOFTCONN;
+                       musb_writeb(mbase, MUSB_POWER, reg);
+               }
+               break;
+
+       case 'c':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_POWER)
+                                       & ~MUSB_POWER_SOFTCONN;
+                       musb_writeb(mbase, MUSB_POWER, reg);
+               }
+               break;
+
+       case 'I':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_POWER)
+                                       | MUSB_POWER_HSENAB;
+                       musb_writeb(mbase, MUSB_POWER, reg);
+               }
+               break;
+
+       case 'i':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_POWER)
+                                       & ~MUSB_POWER_HSENAB;
+                       musb_writeb(mbase, MUSB_POWER, reg);
+               }
+               break;
+
+       case 'F':
+               reg = musb_readb(mbase, MUSB_DEVCTL);
+               reg |= MUSB_DEVCTL_SESSION;
+               musb_writeb(mbase, MUSB_DEVCTL, reg);
+               break;
+
+       case 'H':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_DEVCTL);
+                       reg |= MUSB_DEVCTL_HR;
+                       musb_writeb(mbase, MUSB_DEVCTL, reg);
+                       /* MUSB_HST_MODE( ((struct musb*)data) ); */
+                       /* WARNING("Host Mode\n"); */
+               }
+               break;
+
+       case 'h':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_DEVCTL);
+                       reg &= ~MUSB_DEVCTL_HR;
+                       musb_writeb(mbase, MUSB_DEVCTL, reg);
+               }
+               break;
+
+       case 'T':
+               if (mbase) {
+                       musb_load_testpacket(musb);
+                       musb_writeb(mbase, MUSB_TESTMODE,
+                                       MUSB_TEST_PACKET);
+               }
+               break;
+
+#if (MUSB_DEBUG > 0)
+               /* set/read debug level */
+       case 'D':{
+                       if (count > 1) {
+                               char digits[8], *p = digits;
+                               int i = 0, level = 0, sign = 1;
+                               int len = min(count - 1, (unsigned long)8);
+
+                               if (copy_from_user(&digits, &buffer[1], len))
+                                       return -EFAULT;
+
+                               /* optional sign */
+                               if (*p == '-') {
+                                       len -= 1;
+                                       sign = -sign;
+                                       p++;
+                               }
+
+                               /* read it */
+                               while (i++ < len && *p > '0' && *p < '9') {
+                                       level = level * 10 + (*p - '0');
+                                       p++;
+                               }
+
+                               level *= sign;
+                               DBG(1, "debug level %d\n", level);
+                               debug = level;
+                       }
+               }
+               break;
+
+
+       case '?':
+               INFO("?: you are seeing it\n");
+               INFO("C/c: soft connect enable/disable\n");
+               INFO("I/i: hispeed enable/disable\n");
+               INFO("F: force session start\n");
+               INFO("H: host mode\n");
+               INFO("T: start sending TEST_PACKET\n");
+               INFO("D: set/read dbug level\n");
+               break;
+#endif
+
+       default:
+               ERR("Command %c not implemented\n", cmd);
+               break;
+       }
+
+       musb_platform_try_idle(musb, 0);
+
+       return count;
+}
+
+static int musb_proc_read(char *page, char **start,
+                       off_t off, int count, int *eof, void *data)
+{
+       char *buffer = page;
+       int code = 0;
+       unsigned long   flags;
+       struct musb     *musb = data;
+       unsigned        epnum;
+
+       count -= off;
+       count -= 1;             /* for NUL at end */
+       if (count <= 0)
+               return -EINVAL;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       code = dump_header_stats(musb, buffer);
+       if (code > 0) {
+               buffer += code;
+               count -= code;
+       }
+
+       /* generate the report for the end points */
+       /* REVISIT ... not unless something's connected! */
+       for (epnum = 0; count >= 0 && epnum < musb->nr_endpoints;
+                       epnum++) {
+               code = dump_end_info(musb, epnum, buffer, count);
+               if (code > 0) {
+                       buffer += code;
+                       count -= code;
+               }
+       }
+
+       musb_platform_try_idle(musb, 0);
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+       *eof = 1;
+
+       return buffer - page;
+}
+
+void __devexit musb_debug_delete(char *name, struct musb *musb)
+{
+       if (musb->proc_entry)
+               remove_proc_entry(name, NULL);
+}
+
+struct proc_dir_entry *__init
+musb_debug_create(char *name, struct musb *data)
+{
+       struct proc_dir_entry   *pde;
+
+       /* FIXME convert everything to seq_file; then later, debugfs */
+
+       if (!name)
+               return NULL;
+
+       pde = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, NULL);
+       data->proc_entry = pde;
+       if (pde) {
+               pde->data = data;
+               /* pde->owner = THIS_MODULE; */
+
+               pde->read_proc = musb_proc_read;
+               pde->write_proc = musb_proc_write;
+
+               pde->size = 0;
+
+               pr_debug("Registered /proc/%s\n", name);
+       } else {
+               pr_debug("Cannot create a valid proc file entry");
+       }
+
+       return pde;
+}
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h
new file mode 100644 (file)
index 0000000..9c22866
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * MUSB OTG driver register defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_REGS_H__
+#define __MUSB_REGS_H__
+
+#define MUSB_EP0_FIFOSIZE      64      /* This is non-configurable */
+
+/*
+ * Common USB registers
+ */
+
+#define MUSB_FADDR             0x00    /* 8-bit */
+#define MUSB_POWER             0x01    /* 8-bit */
+
+#define MUSB_INTRTX            0x02    /* 16-bit */
+#define MUSB_INTRRX            0x04
+#define MUSB_INTRTXE           0x06
+#define MUSB_INTRRXE           0x08
+#define MUSB_INTRUSB           0x0A    /* 8 bit */
+#define MUSB_INTRUSBE          0x0B    /* 8 bit */
+#define MUSB_FRAME             0x0C
+#define MUSB_INDEX             0x0E    /* 8 bit */
+#define MUSB_TESTMODE          0x0F    /* 8 bit */
+
+/* Get offset for a given FIFO from musb->mregs */
+#ifdef CONFIG_USB_TUSB6010
+#define MUSB_FIFO_OFFSET(epnum)        (0x200 + ((epnum) * 0x20))
+#else
+#define MUSB_FIFO_OFFSET(epnum)        (0x20 + ((epnum) * 4))
+#endif
+
+/*
+ * Additional Control Registers
+ */
+
+#define MUSB_DEVCTL            0x60    /* 8 bit */
+
+/* These are always controlled through the INDEX register */
+#define MUSB_TXFIFOSZ          0x62    /* 8-bit (see masks) */
+#define MUSB_RXFIFOSZ          0x63    /* 8-bit (see masks) */
+#define MUSB_TXFIFOADD         0x64    /* 16-bit offset shifted right 3 */
+#define MUSB_RXFIFOADD         0x66    /* 16-bit offset shifted right 3 */
+
+/* REVISIT: vctrl/vstatus: optional vendor utmi+phy register at 0x68 */
+#define MUSB_HWVERS            0x6C    /* 8 bit */
+
+#define MUSB_EPINFO            0x78    /* 8 bit */
+#define MUSB_RAMINFO           0x79    /* 8 bit */
+#define MUSB_LINKINFO          0x7a    /* 8 bit */
+#define MUSB_VPLEN             0x7b    /* 8 bit */
+#define MUSB_HS_EOF1           0x7c    /* 8 bit */
+#define MUSB_FS_EOF1           0x7d    /* 8 bit */
+#define MUSB_LS_EOF1           0x7e    /* 8 bit */
+
+/* Offsets to endpoint registers */
+#define MUSB_TXMAXP            0x00
+#define MUSB_TXCSR             0x02
+#define MUSB_CSR0              MUSB_TXCSR      /* Re-used for EP0 */
+#define MUSB_RXMAXP            0x04
+#define MUSB_RXCSR             0x06
+#define MUSB_RXCOUNT           0x08
+#define MUSB_COUNT0            MUSB_RXCOUNT    /* Re-used for EP0 */
+#define MUSB_TXTYPE            0x0A
+#define MUSB_TYPE0             MUSB_TXTYPE     /* Re-used for EP0 */
+#define MUSB_TXINTERVAL                0x0B
+#define MUSB_NAKLIMIT0         MUSB_TXINTERVAL /* Re-used for EP0 */
+#define MUSB_RXTYPE            0x0C
+#define MUSB_RXINTERVAL                0x0D
+#define MUSB_FIFOSIZE          0x0F
+#define MUSB_CONFIGDATA                MUSB_FIFOSIZE   /* Re-used for EP0 */
+
+/* Offsets to endpoint registers in indexed model (using INDEX register) */
+#define MUSB_INDEXED_OFFSET(_epnum, _offset)   \
+       (0x10 + (_offset))
+
+/* Offsets to endpoint registers in flat models */
+#define MUSB_FLAT_OFFSET(_epnum, _offset)      \
+       (0x100 + (0x10*(_epnum)) + (_offset))
+
+#ifdef CONFIG_USB_TUSB6010
+/* TUSB6010 EP0 configuration register is special */
+#define MUSB_TUSB_OFFSET(_epnum, _offset)      \
+       (0x10 + _offset)
+#include "tusb6010.h"          /* Needed "only" for TUSB_EP0_CONF */
+#endif
+
+/* "bus control"/target registers, for host side multipoint (external hubs) */
+#define MUSB_TXFUNCADDR                0x00
+#define MUSB_TXHUBADDR         0x02
+#define MUSB_TXHUBPORT         0x03
+
+#define MUSB_RXFUNCADDR                0x04
+#define MUSB_RXHUBADDR         0x06
+#define MUSB_RXHUBPORT         0x07
+
+#define MUSB_BUSCTL_OFFSET(_epnum, _offset) \
+       (0x80 + (8*(_epnum)) + (_offset))
+
+/*
+ * MUSB Register bits
+ */
+
+/* POWER */
+#define MUSB_POWER_ISOUPDATE   0x80
+#define MUSB_POWER_SOFTCONN    0x40
+#define MUSB_POWER_HSENAB      0x20
+#define MUSB_POWER_HSMODE      0x10
+#define MUSB_POWER_RESET       0x08
+#define MUSB_POWER_RESUME      0x04
+#define MUSB_POWER_SUSPENDM    0x02
+#define MUSB_POWER_ENSUSPEND   0x01
+
+/* INTRUSB */
+#define MUSB_INTR_SUSPEND      0x01
+#define MUSB_INTR_RESUME       0x02
+#define MUSB_INTR_RESET                0x04
+#define MUSB_INTR_BABBLE       0x04
+#define MUSB_INTR_SOF          0x08
+#define MUSB_INTR_CONNECT      0x10
+#define MUSB_INTR_DISCONNECT   0x20
+#define MUSB_INTR_SESSREQ      0x40
+#define MUSB_INTR_VBUSERROR    0x80    /* For SESSION end */
+
+/* DEVCTL */
+#define MUSB_DEVCTL_BDEVICE    0x80
+#define MUSB_DEVCTL_FSDEV      0x40
+#define MUSB_DEVCTL_LSDEV      0x20
+#define MUSB_DEVCTL_VBUS       0x18
+#define MUSB_DEVCTL_VBUS_SHIFT 3
+#define MUSB_DEVCTL_HM         0x04
+#define MUSB_DEVCTL_HR         0x02
+#define MUSB_DEVCTL_SESSION    0x01
+
+/* TESTMODE */
+#define MUSB_TEST_FORCE_HOST   0x80
+#define MUSB_TEST_FIFO_ACCESS  0x40
+#define MUSB_TEST_FORCE_FS     0x20
+#define MUSB_TEST_FORCE_HS     0x10
+#define MUSB_TEST_PACKET       0x08
+#define MUSB_TEST_K            0x04
+#define MUSB_TEST_J            0x02
+#define MUSB_TEST_SE0_NAK      0x01
+
+/* Allocate for double-packet buffering (effectively doubles assigned _SIZE) */
+#define MUSB_FIFOSZ_DPB        0x10
+/* Allocation size (8, 16, 32, ... 4096) */
+#define MUSB_FIFOSZ_SIZE       0x0f
+
+/* CSR0 */
+#define MUSB_CSR0_FLUSHFIFO    0x0100
+#define MUSB_CSR0_TXPKTRDY     0x0002
+#define MUSB_CSR0_RXPKTRDY     0x0001
+
+/* CSR0 in Peripheral mode */
+#define MUSB_CSR0_P_SVDSETUPEND        0x0080
+#define MUSB_CSR0_P_SVDRXPKTRDY        0x0040
+#define MUSB_CSR0_P_SENDSTALL  0x0020
+#define MUSB_CSR0_P_SETUPEND   0x0010
+#define MUSB_CSR0_P_DATAEND    0x0008
+#define MUSB_CSR0_P_SENTSTALL  0x0004
+
+/* CSR0 in Host mode */
+#define MUSB_CSR0_H_DIS_PING           0x0800
+#define MUSB_CSR0_H_WR_DATATOGGLE      0x0400  /* Set to allow setting: */
+#define MUSB_CSR0_H_DATATOGGLE         0x0200  /* Data toggle control */
+#define MUSB_CSR0_H_NAKTIMEOUT         0x0080
+#define MUSB_CSR0_H_STATUSPKT          0x0040
+#define MUSB_CSR0_H_REQPKT             0x0020
+#define MUSB_CSR0_H_ERROR              0x0010
+#define MUSB_CSR0_H_SETUPPKT           0x0008
+#define MUSB_CSR0_H_RXSTALL            0x0004
+
+/* CSR0 bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_CSR0_P_WZC_BITS   \
+       (MUSB_CSR0_P_SENTSTALL)
+#define MUSB_CSR0_H_WZC_BITS   \
+       (MUSB_CSR0_H_NAKTIMEOUT | MUSB_CSR0_H_RXSTALL \
+       | MUSB_CSR0_RXPKTRDY)
+
+/* TxType/RxType */
+#define MUSB_TYPE_SPEED                0xc0
+#define MUSB_TYPE_SPEED_SHIFT  6
+#define MUSB_TYPE_PROTO                0x30    /* Implicitly zero for ep0 */
+#define MUSB_TYPE_PROTO_SHIFT  4
+#define MUSB_TYPE_REMOTE_END   0xf     /* Implicitly zero for ep0 */
+
+/* CONFIGDATA */
+#define MUSB_CONFIGDATA_MPRXE          0x80    /* Auto bulk pkt combining */
+#define MUSB_CONFIGDATA_MPTXE          0x40    /* Auto bulk pkt splitting */
+#define MUSB_CONFIGDATA_BIGENDIAN      0x20
+#define MUSB_CONFIGDATA_HBRXE          0x10    /* HB-ISO for RX */
+#define MUSB_CONFIGDATA_HBTXE          0x08    /* HB-ISO for TX */
+#define MUSB_CONFIGDATA_DYNFIFO                0x04    /* Dynamic FIFO sizing */
+#define MUSB_CONFIGDATA_SOFTCONE       0x02    /* SoftConnect */
+#define MUSB_CONFIGDATA_UTMIDW         0x01    /* Data width 0/1 => 8/16bits */
+
+/* TXCSR in Peripheral and Host mode */
+#define MUSB_TXCSR_AUTOSET             0x8000
+#define MUSB_TXCSR_MODE                        0x2000
+#define MUSB_TXCSR_DMAENAB             0x1000
+#define MUSB_TXCSR_FRCDATATOG          0x0800
+#define MUSB_TXCSR_DMAMODE             0x0400
+#define MUSB_TXCSR_CLRDATATOG          0x0040
+#define MUSB_TXCSR_FLUSHFIFO           0x0008
+#define MUSB_TXCSR_FIFONOTEMPTY                0x0002
+#define MUSB_TXCSR_TXPKTRDY            0x0001
+
+/* TXCSR in Peripheral mode */
+#define MUSB_TXCSR_P_ISO               0x4000
+#define MUSB_TXCSR_P_INCOMPTX          0x0080
+#define MUSB_TXCSR_P_SENTSTALL         0x0020
+#define MUSB_TXCSR_P_SENDSTALL         0x0010
+#define MUSB_TXCSR_P_UNDERRUN          0x0004
+
+/* TXCSR in Host mode */
+#define MUSB_TXCSR_H_WR_DATATOGGLE     0x0200
+#define MUSB_TXCSR_H_DATATOGGLE                0x0100
+#define MUSB_TXCSR_H_NAKTIMEOUT                0x0080
+#define MUSB_TXCSR_H_RXSTALL           0x0020
+#define MUSB_TXCSR_H_ERROR             0x0004
+
+/* TXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_TXCSR_P_WZC_BITS  \
+       (MUSB_TXCSR_P_INCOMPTX | MUSB_TXCSR_P_SENTSTALL \
+       | MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_FIFONOTEMPTY)
+#define MUSB_TXCSR_H_WZC_BITS  \
+       (MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \
+       | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY)
+
+/* RXCSR in Peripheral and Host mode */
+#define MUSB_RXCSR_AUTOCLEAR           0x8000
+#define MUSB_RXCSR_DMAENAB             0x2000
+#define MUSB_RXCSR_DISNYET             0x1000
+#define MUSB_RXCSR_PID_ERR             0x1000
+#define MUSB_RXCSR_DMAMODE             0x0800
+#define MUSB_RXCSR_INCOMPRX            0x0100
+#define MUSB_RXCSR_CLRDATATOG          0x0080
+#define MUSB_RXCSR_FLUSHFIFO           0x0010
+#define MUSB_RXCSR_DATAERROR           0x0008
+#define MUSB_RXCSR_FIFOFULL            0x0002
+#define MUSB_RXCSR_RXPKTRDY            0x0001
+
+/* RXCSR in Peripheral mode */
+#define MUSB_RXCSR_P_ISO               0x4000
+#define MUSB_RXCSR_P_SENTSTALL         0x0040
+#define MUSB_RXCSR_P_SENDSTALL         0x0020
+#define MUSB_RXCSR_P_OVERRUN           0x0004
+
+/* RXCSR in Host mode */
+#define MUSB_RXCSR_H_AUTOREQ           0x4000
+#define MUSB_RXCSR_H_WR_DATATOGGLE     0x0400
+#define MUSB_RXCSR_H_DATATOGGLE                0x0200
+#define MUSB_RXCSR_H_RXSTALL           0x0040
+#define MUSB_RXCSR_H_REQPKT            0x0020
+#define MUSB_RXCSR_H_ERROR             0x0004
+
+/* RXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_RXCSR_P_WZC_BITS  \
+       (MUSB_RXCSR_P_SENTSTALL | MUSB_RXCSR_P_OVERRUN \
+       | MUSB_RXCSR_RXPKTRDY)
+#define MUSB_RXCSR_H_WZC_BITS  \
+       (MUSB_RXCSR_H_RXSTALL | MUSB_RXCSR_H_ERROR \
+       | MUSB_RXCSR_DATAERROR | MUSB_RXCSR_RXPKTRDY)
+
+/* HUBADDR */
+#define MUSB_HUBADDR_MULTI_TT          0x80
+
+#endif /* __MUSB_REGS_H__ */
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
new file mode 100644 (file)
index 0000000..e0e9ce5
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ * MUSB OTG driver virtual root hub support
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+
+#include <asm/unaligned.h>
+
+#include "musb_core.h"
+
+
+static void musb_port_suspend(struct musb *musb, bool do_suspend)
+{
+       u8              power;
+       void __iomem    *mbase = musb->mregs;
+
+       if (!is_host_active(musb))
+               return;
+
+       /* NOTE:  this doesn't necessarily put PHY into low power mode,
+        * turning off its clock; that's a function of PHY integration and
+        * MUSB_POWER_ENSUSPEND.  PHY may need a clock (sigh) to detect
+        * SE0 changing to connect (J) or wakeup (K) states.
+        */
+       power = musb_readb(mbase, MUSB_POWER);
+       if (do_suspend) {
+               int retries = 10000;
+
+               power &= ~MUSB_POWER_RESUME;
+               power |= MUSB_POWER_SUSPENDM;
+               musb_writeb(mbase, MUSB_POWER, power);
+
+               /* Needed for OPT A tests */
+               power = musb_readb(mbase, MUSB_POWER);
+               while (power & MUSB_POWER_SUSPENDM) {
+                       power = musb_readb(mbase, MUSB_POWER);
+                       if (retries-- < 1)
+                               break;
+               }
+
+               DBG(3, "Root port suspended, power %02x\n", power);
+
+               musb->port1_status |= USB_PORT_STAT_SUSPEND;
+               switch (musb->xceiv.state) {
+               case OTG_STATE_A_HOST:
+                       musb->xceiv.state = OTG_STATE_A_SUSPEND;
+                       musb->is_active = is_otg_enabled(musb)
+                                       && musb->xceiv.host->b_hnp_enable;
+                       musb_platform_try_idle(musb, 0);
+                       break;
+#ifdef CONFIG_USB_MUSB_OTG
+               case OTG_STATE_B_HOST:
+                       musb->xceiv.state = OTG_STATE_B_WAIT_ACON;
+                       musb->is_active = is_otg_enabled(musb)
+                                       && musb->xceiv.host->b_hnp_enable;
+                       musb_platform_try_idle(musb, 0);
+                       break;
+#endif
+               default:
+                       DBG(1, "bogus rh suspend? %s\n",
+                               otg_state_string(musb));
+               }
+       } else if (power & MUSB_POWER_SUSPENDM) {
+               power &= ~MUSB_POWER_SUSPENDM;
+               power |= MUSB_POWER_RESUME;
+               musb_writeb(mbase, MUSB_POWER, power);
+
+               DBG(3, "Root port resuming, power %02x\n", power);
+
+               /* later, GetPortStatus will stop RESUME signaling */
+               musb->port1_status |= MUSB_PORT_STAT_RESUME;
+               musb->rh_timer = jiffies + msecs_to_jiffies(20);
+       }
+}
+
+static void musb_port_reset(struct musb *musb, bool do_reset)
+{
+       u8              power;
+       void __iomem    *mbase = musb->mregs;
+
+#ifdef CONFIG_USB_MUSB_OTG
+       if (musb->xceiv.state == OTG_STATE_B_IDLE) {
+               DBG(2, "HNP: Returning from HNP; no hub reset from b_idle\n");
+               musb->port1_status &= ~USB_PORT_STAT_RESET;
+               return;
+       }
+#endif
+
+       if (!is_host_active(musb))
+               return;
+
+       /* NOTE:  caller guarantees it will turn off the reset when
+        * the appropriate amount of time has passed
+        */
+       power = musb_readb(mbase, MUSB_POWER);
+       if (do_reset) {
+
+               /*
+                * If RESUME is set, we must make sure it stays minimum 20 ms.
+                * Then we must clear RESUME and wait a bit to let musb start
+                * generating SOFs. If we don't do this, OPT HS A 6.8 tests
+                * fail with "Error! Did not receive an SOF before suspend
+                * detected".
+                */
+               if (power &  MUSB_POWER_RESUME) {
+                       while (time_before(jiffies, musb->rh_timer))
+                               msleep(1);
+                       musb_writeb(mbase, MUSB_POWER,
+                               power & ~MUSB_POWER_RESUME);
+                       msleep(1);
+               }
+
+               musb->ignore_disconnect = true;
+               power &= 0xf0;
+               musb_writeb(mbase, MUSB_POWER,
+                               power | MUSB_POWER_RESET);
+
+               musb->port1_status |= USB_PORT_STAT_RESET;
+               musb->port1_status &= ~USB_PORT_STAT_ENABLE;
+               musb->rh_timer = jiffies + msecs_to_jiffies(50);
+       } else {
+               DBG(4, "root port reset stopped\n");
+               musb_writeb(mbase, MUSB_POWER,
+                               power & ~MUSB_POWER_RESET);
+
+               musb->ignore_disconnect = false;
+
+               power = musb_readb(mbase, MUSB_POWER);
+               if (power & MUSB_POWER_HSMODE) {
+                       DBG(4, "high-speed device connected\n");
+                       musb->port1_status |= USB_PORT_STAT_HIGH_SPEED;
+               }
+
+               musb->port1_status &= ~USB_PORT_STAT_RESET;
+               musb->port1_status |= USB_PORT_STAT_ENABLE
+                                       | (USB_PORT_STAT_C_RESET << 16)
+                                       | (USB_PORT_STAT_C_ENABLE << 16);
+               usb_hcd_poll_rh_status(musb_to_hcd(musb));
+
+               musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
+       }
+}
+
+void musb_root_disconnect(struct musb *musb)
+{
+       musb->port1_status = (1 << USB_PORT_FEAT_POWER)
+                       | (1 << USB_PORT_FEAT_C_CONNECTION);
+
+       usb_hcd_poll_rh_status(musb_to_hcd(musb));
+       musb->is_active = 0;
+
+       switch (musb->xceiv.state) {
+       case OTG_STATE_A_HOST:
+       case OTG_STATE_A_SUSPEND:
+               musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
+               musb->is_active = 0;
+               break;
+       case OTG_STATE_A_WAIT_VFALL:
+               musb->xceiv.state = OTG_STATE_B_IDLE;
+               break;
+       default:
+               DBG(1, "host disconnect (%s)\n", otg_state_string(musb));
+       }
+}
+
+
+/*---------------------------------------------------------------------*/
+
+/* Caller may or may not hold musb->lock */
+int musb_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+       struct musb     *musb = hcd_to_musb(hcd);
+       int             retval = 0;
+
+       /* called in_irq() via usb_hcd_poll_rh_status() */
+       if (musb->port1_status & 0xffff0000) {
+               *buf = 0x02;
+               retval = 1;
+       }
+       return retval;
+}
+
+int musb_hub_control(
+       struct usb_hcd  *hcd,
+       u16             typeReq,
+       u16             wValue,
+       u16             wIndex,
+       char            *buf,
+       u16             wLength)
+{
+       struct musb     *musb = hcd_to_musb(hcd);
+       u32             temp;
+       int             retval = 0;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
+               spin_unlock_irqrestore(&musb->lock, flags);
+               return -ESHUTDOWN;
+       }
+
+       /* hub features:  always zero, setting is a NOP
+        * port features: reported, sometimes updated when host is active
+        * no indicators
+        */
+       switch (typeReq) {
+       case ClearHubFeature:
+       case SetHubFeature:
+               switch (wValue) {
+               case C_HUB_OVER_CURRENT:
+               case C_HUB_LOCAL_POWER:
+                       break;
+               default:
+                       goto error;
+               }
+               break;
+       case ClearPortFeature:
+               if ((wIndex & 0xff) != 1)
+                       goto error;
+
+               switch (wValue) {
+               case USB_PORT_FEAT_ENABLE:
+                       break;
+               case USB_PORT_FEAT_SUSPEND:
+                       musb_port_suspend(musb, false);
+                       break;
+               case USB_PORT_FEAT_POWER:
+                       if (!(is_otg_enabled(musb) && hcd->self.is_b_host))
+                               musb_set_vbus(musb, 0);
+                       break;
+               case USB_PORT_FEAT_C_CONNECTION:
+               case USB_PORT_FEAT_C_ENABLE:
+               case USB_PORT_FEAT_C_OVER_CURRENT:
+               case USB_PORT_FEAT_C_RESET:
+               case USB_PORT_FEAT_C_SUSPEND:
+                       break;
+               default:
+                       goto error;
+               }
+               DBG(5, "clear feature %d\n", wValue);
+               musb->port1_status &= ~(1 << wValue);
+               break;
+       case GetHubDescriptor:
+               {
+               struct usb_hub_descriptor *desc = (void *)buf;
+
+               desc->bDescLength = 9;
+               desc->bDescriptorType = 0x29;
+               desc->bNbrPorts = 1;
+               desc->wHubCharacteristics = __constant_cpu_to_le16(
+                                 0x0001        /* per-port power switching */
+                               | 0x0010        /* no overcurrent reporting */
+                               );
+               desc->bPwrOn2PwrGood = 5;       /* msec/2 */
+               desc->bHubContrCurrent = 0;
+
+               /* workaround bogus struct definition */
+               desc->DeviceRemovable[0] = 0x02;        /* port 1 */
+               desc->DeviceRemovable[1] = 0xff;
+               }
+               break;
+       case GetHubStatus:
+               temp = 0;
+               *(__le32 *) buf = cpu_to_le32(temp);
+               break;
+       case GetPortStatus:
+               if (wIndex != 1)
+                       goto error;
+
+               /* finish RESET signaling? */
+               if ((musb->port1_status & USB_PORT_STAT_RESET)
+                               && time_after_eq(jiffies, musb->rh_timer))
+                       musb_port_reset(musb, false);
+
+               /* finish RESUME signaling? */
+               if ((musb->port1_status & MUSB_PORT_STAT_RESUME)
+                               && time_after_eq(jiffies, musb->rh_timer)) {
+                       u8              power;
+
+                       power = musb_readb(musb->mregs, MUSB_POWER);
+                       power &= ~MUSB_POWER_RESUME;
+                       DBG(4, "root port resume stopped, power %02x\n",
+                                       power);
+                       musb_writeb(musb->mregs, MUSB_POWER, power);
+
+                       /* ISSUE:  DaVinci (RTL 1.300) disconnects after
+                        * resume of high speed peripherals (but not full
+                        * speed ones).
+                        */
+
+                       musb->is_active = 1;
+                       musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
+                                       | MUSB_PORT_STAT_RESUME);
+                       musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
+                       usb_hcd_poll_rh_status(musb_to_hcd(musb));
+                       /* NOTE: it might really be A_WAIT_BCON ... */
+                       musb->xceiv.state = OTG_STATE_A_HOST;
+               }
+
+               put_unaligned(cpu_to_le32(musb->port1_status
+                                       & ~MUSB_PORT_STAT_RESUME),
+                               (__le32 *) buf);
+
+               /* port change status is more interesting */
+               DBG(get_unaligned((u16 *)(buf+2)) ? 2 : 5, "port status %08x\n",
+                               musb->port1_status);
+               break;
+       case SetPortFeature:
+               if ((wIndex & 0xff) != 1)
+                       goto error;
+
+               switch (wValue) {
+               case USB_PORT_FEAT_POWER:
+                       /* NOTE: this controller has a strange state machine
+                        * that involves "requesting sessions" according to
+                        * magic side effects from incompletely-described
+                        * rules about startup...
+                        *
+                        * This call is what really starts the host mode; be
+                        * very careful about side effects if you reorder any
+                        * initialization logic, e.g. for OTG, or change any
+                        * logic relating to VBUS power-up.
+                        */
+                       if (!(is_otg_enabled(musb) && hcd->self.is_b_host))
+                               musb_start(musb);
+                       break;
+               case USB_PORT_FEAT_RESET:
+                       musb_port_reset(musb, true);
+                       break;
+               case USB_PORT_FEAT_SUSPEND:
+                       musb_port_suspend(musb, true);
+                       break;
+               case USB_PORT_FEAT_TEST:
+                       if (unlikely(is_host_active(musb)))
+                               goto error;
+
+                       wIndex >>= 8;
+                       switch (wIndex) {
+                       case 1:
+                               pr_debug("TEST_J\n");
+                               temp = MUSB_TEST_J;
+                               break;
+                       case 2:
+                               pr_debug("TEST_K\n");
+                               temp = MUSB_TEST_K;
+                               break;
+                       case 3:
+                               pr_debug("TEST_SE0_NAK\n");
+                               temp = MUSB_TEST_SE0_NAK;
+                               break;
+                       case 4:
+                               pr_debug("TEST_PACKET\n");
+                               temp = MUSB_TEST_PACKET;
+                               musb_load_testpacket(musb);
+                               break;
+                       case 5:
+                               pr_debug("TEST_FORCE_ENABLE\n");
+                               temp = MUSB_TEST_FORCE_HOST
+                                       | MUSB_TEST_FORCE_HS;
+
+                               musb_writeb(musb->mregs, MUSB_DEVCTL,
+                                               MUSB_DEVCTL_SESSION);
+                               break;
+                       case 6:
+                               pr_debug("TEST_FIFO_ACCESS\n");
+                               temp = MUSB_TEST_FIFO_ACCESS;
+                               break;
+                       default:
+                               goto error;
+                       }
+                       musb_writeb(musb->mregs, MUSB_TESTMODE, temp);
+                       break;
+               default:
+                       goto error;
+               }
+               DBG(5, "set feature %d\n", wValue);
+               musb->port1_status |= 1 << wValue;
+               break;
+
+       default:
+error:
+               /* "protocol stall" on error */
+               retval = -EPIPE;
+       }
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return retval;
+}
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
new file mode 100644 (file)
index 0000000..9ba8fb7
--- /dev/null
@@ -0,0 +1,433 @@
+/*
+ * MUSB OTG driver - support for Mentor's DMA controller
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2007 by Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include "musb_core.h"
+
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+#include "omap2430.h"
+#endif
+
+#define MUSB_HSDMA_BASE                0x200
+#define MUSB_HSDMA_INTR                (MUSB_HSDMA_BASE + 0)
+#define MUSB_HSDMA_CONTROL             0x4
+#define MUSB_HSDMA_ADDRESS             0x8
+#define MUSB_HSDMA_COUNT               0xc
+
+#define MUSB_HSDMA_CHANNEL_OFFSET(_bChannel, _offset)          \
+               (MUSB_HSDMA_BASE + (_bChannel << 4) + _offset)
+
+/* control register (16-bit): */
+#define MUSB_HSDMA_ENABLE_SHIFT                0
+#define MUSB_HSDMA_TRANSMIT_SHIFT              1
+#define MUSB_HSDMA_MODE1_SHIFT         2
+#define MUSB_HSDMA_IRQENABLE_SHIFT             3
+#define MUSB_HSDMA_ENDPOINT_SHIFT              4
+#define MUSB_HSDMA_BUSERROR_SHIFT              8
+#define MUSB_HSDMA_BURSTMODE_SHIFT             9
+#define MUSB_HSDMA_BURSTMODE           (3 << MUSB_HSDMA_BURSTMODE_SHIFT)
+#define MUSB_HSDMA_BURSTMODE_UNSPEC    0
+#define MUSB_HSDMA_BURSTMODE_INCR4     1
+#define MUSB_HSDMA_BURSTMODE_INCR8     2
+#define MUSB_HSDMA_BURSTMODE_INCR16    3
+
+#define MUSB_HSDMA_CHANNELS            8
+
+struct musb_dma_controller;
+
+struct musb_dma_channel {
+       struct dma_channel              Channel;
+       struct musb_dma_controller      *controller;
+       u32                             dwStartAddress;
+       u32                             len;
+       u16                             wMaxPacketSize;
+       u8                              bIndex;
+       u8                              epnum;
+       u8                              transmit;
+};
+
+struct musb_dma_controller {
+       struct dma_controller           Controller;
+       struct musb_dma_channel         aChannel[MUSB_HSDMA_CHANNELS];
+       void                            *pDmaPrivate;
+       void __iomem                    *pCoreBase;
+       u8                              bChannelCount;
+       u8                              bmUsedChannels;
+       u8                              irq;
+};
+
+static int dma_controller_start(struct dma_controller *c)
+{
+       /* nothing to do */
+       return 0;
+}
+
+static void dma_channel_release(struct dma_channel *pChannel);
+
+static int dma_controller_stop(struct dma_controller *c)
+{
+       struct musb_dma_controller *controller =
+               container_of(c, struct musb_dma_controller, Controller);
+       struct musb *musb = (struct musb *) controller->pDmaPrivate;
+       struct dma_channel *pChannel;
+       u8 bBit;
+
+       if (controller->bmUsedChannels != 0) {
+               dev_err(musb->controller,
+                       "Stopping DMA controller while channel active\n");
+
+               for (bBit = 0; bBit < MUSB_HSDMA_CHANNELS; bBit++) {
+                       if (controller->bmUsedChannels & (1 << bBit)) {
+                               pChannel = &controller->aChannel[bBit].Channel;
+                               dma_channel_release(pChannel);
+
+                               if (!controller->bmUsedChannels)
+                                       break;
+                       }
+               }
+       }
+       return 0;
+}
+
+static struct dma_channel *dma_channel_allocate(struct dma_controller *c,
+                               struct musb_hw_ep *hw_ep, u8 transmit)
+{
+       u8 bBit;
+       struct dma_channel *pChannel = NULL;
+       struct musb_dma_channel *pImplChannel = NULL;
+       struct musb_dma_controller *controller =
+                       container_of(c, struct musb_dma_controller, Controller);
+
+       for (bBit = 0; bBit < MUSB_HSDMA_CHANNELS; bBit++) {
+               if (!(controller->bmUsedChannels & (1 << bBit))) {
+                       controller->bmUsedChannels |= (1 << bBit);
+                       pImplChannel = &(controller->aChannel[bBit]);
+                       pImplChannel->controller = controller;
+                       pImplChannel->bIndex = bBit;
+                       pImplChannel->epnum = hw_ep->epnum;
+                       pImplChannel->transmit = transmit;
+                       pChannel = &(pImplChannel->Channel);
+                       pChannel->private_data = pImplChannel;
+                       pChannel->status = MUSB_DMA_STATUS_FREE;
+                       pChannel->max_len = 0x10000;
+                       /* Tx => mode 1; Rx => mode 0 */
+                       pChannel->desired_mode = transmit;
+                       pChannel->actual_len = 0;
+                       break;
+               }
+       }
+       return pChannel;
+}
+
+static void dma_channel_release(struct dma_channel *pChannel)
+{
+       struct musb_dma_channel *pImplChannel =
+               (struct musb_dma_channel *) pChannel->private_data;
+
+       pChannel->actual_len = 0;
+       pImplChannel->dwStartAddress = 0;
+       pImplChannel->len = 0;
+
+       pImplChannel->controller->bmUsedChannels &=
+               ~(1 << pImplChannel->bIndex);
+
+       pChannel->status = MUSB_DMA_STATUS_UNKNOWN;
+}
+
+static void configure_channel(struct dma_channel *pChannel,
+                               u16 packet_sz, u8 mode,
+                               dma_addr_t dma_addr, u32 len)
+{
+       struct musb_dma_channel *pImplChannel =
+               (struct musb_dma_channel *) pChannel->private_data;
+       struct musb_dma_controller *controller = pImplChannel->controller;
+       void __iomem *mbase = controller->pCoreBase;
+       u8 bChannel = pImplChannel->bIndex;
+       u16 csr = 0;
+
+       DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n",
+                       pChannel, packet_sz, dma_addr, len, mode);
+
+       if (mode) {
+               csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;
+               BUG_ON(len < packet_sz);
+
+               if (packet_sz >= 64) {
+                       csr |= MUSB_HSDMA_BURSTMODE_INCR16
+                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
+               } else if (packet_sz >= 32) {
+                       csr |= MUSB_HSDMA_BURSTMODE_INCR8
+                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
+               } else if (packet_sz >= 16) {
+                       csr |= MUSB_HSDMA_BURSTMODE_INCR4
+                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
+               }
+       }
+
+       csr |= (pImplChannel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
+               | (1 << MUSB_HSDMA_ENABLE_SHIFT)
+               | (1 << MUSB_HSDMA_IRQENABLE_SHIFT)
+               | (pImplChannel->transmit
+                               ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT)
+                               : 0);
+
+       /* address/count */
+       musb_writel(mbase,
+               MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS),
+               dma_addr);
+       musb_writel(mbase,
+               MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT),
+               len);
+
+       /* control (this should start things) */
+       musb_writew(mbase,
+               MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL),
+               csr);
+}
+
+static int dma_channel_program(struct dma_channel *pChannel,
+                               u16 packet_sz, u8 mode,
+                               dma_addr_t dma_addr, u32 len)
+{
+       struct musb_dma_channel *pImplChannel =
+                       (struct musb_dma_channel *) pChannel->private_data;
+
+       DBG(2, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n",
+               pImplChannel->epnum,
+               pImplChannel->transmit ? "Tx" : "Rx",
+               packet_sz, dma_addr, len, mode);
+
+       BUG_ON(pChannel->status == MUSB_DMA_STATUS_UNKNOWN ||
+               pChannel->status == MUSB_DMA_STATUS_BUSY);
+
+       pChannel->actual_len = 0;
+       pImplChannel->dwStartAddress = dma_addr;
+       pImplChannel->len = len;
+       pImplChannel->wMaxPacketSize = packet_sz;
+       pChannel->status = MUSB_DMA_STATUS_BUSY;
+
+       if ((mode == 1) && (len >= packet_sz))
+               configure_channel(pChannel, packet_sz, 1, dma_addr, len);
+       else
+               configure_channel(pChannel, packet_sz, 0, dma_addr, len);
+
+       return true;
+}
+
+static int dma_channel_abort(struct dma_channel *pChannel)
+{
+       struct musb_dma_channel *pImplChannel =
+               (struct musb_dma_channel *) pChannel->private_data;
+       u8 bChannel = pImplChannel->bIndex;
+       void __iomem *mbase = pImplChannel->controller->pCoreBase;
+       u16 csr;
+
+       if (pChannel->status == MUSB_DMA_STATUS_BUSY) {
+               if (pImplChannel->transmit) {
+
+                       csr = musb_readw(mbase,
+                               MUSB_EP_OFFSET(pImplChannel->epnum,
+                                               MUSB_TXCSR));
+                       csr &= ~(MUSB_TXCSR_AUTOSET |
+                                MUSB_TXCSR_DMAENAB |
+                                MUSB_TXCSR_DMAMODE);
+                       musb_writew(mbase,
+                               MUSB_EP_OFFSET(pImplChannel->epnum,
+                                               MUSB_TXCSR),
+                               csr);
+               } else {
+                       csr = musb_readw(mbase,
+                               MUSB_EP_OFFSET(pImplChannel->epnum,
+                                               MUSB_RXCSR));
+                       csr &= ~(MUSB_RXCSR_AUTOCLEAR |
+                                MUSB_RXCSR_DMAENAB |
+                                MUSB_RXCSR_DMAMODE);
+                       musb_writew(mbase,
+                               MUSB_EP_OFFSET(pImplChannel->epnum,
+                                               MUSB_RXCSR),
+                               csr);
+               }
+
+               musb_writew(mbase,
+                       MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL),
+                       0);
+               musb_writel(mbase,
+                       MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS),
+                       0);
+               musb_writel(mbase,
+                       MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT),
+                       0);
+
+               pChannel->status = MUSB_DMA_STATUS_FREE;
+       }
+       return 0;
+}
+
+static irqreturn_t dma_controller_irq(int irq, void *private_data)
+{
+       struct musb_dma_controller *controller =
+               (struct musb_dma_controller *)private_data;
+       struct musb_dma_channel *pImplChannel;
+       struct musb *musb = controller->pDmaPrivate;
+       void __iomem *mbase = controller->pCoreBase;
+       struct dma_channel *pChannel;
+       u8 bChannel;
+       u16 csr;
+       u32 dwAddress;
+       u8 int_hsdma;
+       irqreturn_t retval = IRQ_NONE;
+       unsigned long flags;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR);
+       if (!int_hsdma)
+               goto done;
+
+       for (bChannel = 0; bChannel < MUSB_HSDMA_CHANNELS; bChannel++) {
+               if (int_hsdma & (1 << bChannel)) {
+                       pImplChannel = (struct musb_dma_channel *)
+                                       &(controller->aChannel[bChannel]);
+                       pChannel = &pImplChannel->Channel;
+
+                       csr = musb_readw(mbase,
+                                       MUSB_HSDMA_CHANNEL_OFFSET(bChannel,
+                                                       MUSB_HSDMA_CONTROL));
+
+                       if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT))
+                               pImplChannel->Channel.status =
+                                       MUSB_DMA_STATUS_BUS_ABORT;
+                       else {
+                               u8 devctl;
+
+                               dwAddress = musb_readl(mbase,
+                                               MUSB_HSDMA_CHANNEL_OFFSET(
+                                                       bChannel,
+                                                       MUSB_HSDMA_ADDRESS));
+                               pChannel->actual_len = dwAddress
+                                       - pImplChannel->dwStartAddress;
+
+                               DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n",
+                                       pChannel, pImplChannel->dwStartAddress,
+                                       dwAddress, pChannel->actual_len,
+                                       pImplChannel->len,
+                                       (pChannel->actual_len
+                                               < pImplChannel->len) ?
+                                       "=> reconfig 0" : "=> complete");
+
+                               devctl = musb_readb(mbase, MUSB_DEVCTL);
+
+                               pChannel->status = MUSB_DMA_STATUS_FREE;
+
+                               /* completed */
+                               if ((devctl & MUSB_DEVCTL_HM)
+                                       && (pImplChannel->transmit)
+                                       && ((pChannel->desired_mode == 0)
+                                           || (pChannel->actual_len &
+                                           (pImplChannel->wMaxPacketSize - 1)))
+                                        ) {
+                                       /* Send out the packet */
+                                       musb_ep_select(mbase,
+                                               pImplChannel->epnum);
+                                       musb_writew(mbase, MUSB_EP_OFFSET(
+                                                       pImplChannel->epnum,
+                                                       MUSB_TXCSR),
+                                               MUSB_TXCSR_TXPKTRDY);
+                               } else
+                                       musb_dma_completion(
+                                               musb,
+                                               pImplChannel->epnum,
+                                               pImplChannel->transmit);
+                       }
+               }
+       }
+       retval = IRQ_HANDLED;
+done:
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return retval;
+}
+
+void dma_controller_destroy(struct dma_controller *c)
+{
+       struct musb_dma_controller *controller;
+
+       controller = container_of(c, struct musb_dma_controller, Controller);
+       if (!controller)
+               return;
+
+       if (controller->irq)
+               free_irq(controller->irq, c);
+
+       kfree(controller);
+}
+
+struct dma_controller *__init
+dma_controller_create(struct musb *musb, void __iomem *pCoreBase)
+{
+       struct musb_dma_controller *controller;
+       struct device *dev = musb->controller;
+       struct platform_device *pdev = to_platform_device(dev);
+       int irq = platform_get_irq(pdev, 1);
+
+       if (irq == 0) {
+               dev_err(dev, "No DMA interrupt line!\n");
+               return NULL;
+       }
+
+       controller = kzalloc(sizeof(struct musb_dma_controller), GFP_KERNEL);
+       if (!controller)
+               return NULL;
+
+       controller->bChannelCount = MUSB_HSDMA_CHANNELS;
+       controller->pDmaPrivate = musb;
+       controller->pCoreBase = pCoreBase;
+
+       controller->Controller.start = dma_controller_start;
+       controller->Controller.stop = dma_controller_stop;
+       controller->Controller.channel_alloc = dma_channel_allocate;
+       controller->Controller.channel_release = dma_channel_release;
+       controller->Controller.channel_program = dma_channel_program;
+       controller->Controller.channel_abort = dma_channel_abort;
+
+       if (request_irq(irq, dma_controller_irq, IRQF_DISABLED,
+                       musb->controller->bus_id, &controller->Controller)) {
+               dev_err(dev, "request_irq %d failed!\n", irq);
+               dma_controller_destroy(&controller->Controller);
+               return NULL;
+       }
+
+       controller->irq = irq;
+
+       return &controller->Controller;
+}
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
new file mode 100644 (file)
index 0000000..298b22e
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2005-2007 by Texas Instruments
+ * Some code has been taken from tusb6010.c
+ * Copyrights for that are attributable to:
+ * Copyright (C) 2006 Nokia Corporation
+ * Jarkko Nikula <jarkko.nikula@nokia.com>
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ *
+ * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/mux.h>
+
+#include "musb_core.h"
+#include "omap2430.h"
+
+#ifdef CONFIG_ARCH_OMAP3430
+#define        get_cpu_rev()   2
+#endif
+
+#define MUSB_TIMEOUT_A_WAIT_BCON       1100
+
+static struct timer_list musb_idle_timer;
+
+static void musb_do_idle(unsigned long _musb)
+{
+       struct musb     *musb = (void *)_musb;
+       unsigned long   flags;
+       u8      power;
+       u8      devctl;
+
+       devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       switch (musb->xceiv.state) {
+       case OTG_STATE_A_WAIT_BCON:
+               devctl &= ~MUSB_DEVCTL_SESSION;
+               musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+               devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+               if (devctl & MUSB_DEVCTL_BDEVICE) {
+                       musb->xceiv.state = OTG_STATE_B_IDLE;
+                       MUSB_DEV_MODE(musb);
+               } else {
+                       musb->xceiv.state = OTG_STATE_A_IDLE;
+                       MUSB_HST_MODE(musb);
+               }
+               break;
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       case OTG_STATE_A_SUSPEND:
+               /* finish RESUME signaling? */
+               if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
+                       power = musb_readb(musb->mregs, MUSB_POWER);
+                       power &= ~MUSB_POWER_RESUME;
+                       DBG(1, "root port resume stopped, power %02x\n", power);
+                       musb_writeb(musb->mregs, MUSB_POWER, power);
+                       musb->is_active = 1;
+                       musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
+                                               | MUSB_PORT_STAT_RESUME);
+                       musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
+                       usb_hcd_poll_rh_status(musb_to_hcd(musb));
+                       /* NOTE: it might really be A_WAIT_BCON ... */
+                       musb->xceiv.state = OTG_STATE_A_HOST;
+               }
+               break;
+#endif
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       case OTG_STATE_A_HOST:
+               devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+               if (devctl &  MUSB_DEVCTL_BDEVICE)
+                       musb->xceiv.state = OTG_STATE_B_IDLE;
+               else
+                       musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
+#endif
+       default:
+               break;
+       }
+       spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+
+void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+{
+       unsigned long           default_timeout = jiffies + msecs_to_jiffies(3);
+       static unsigned long    last_timer;
+
+       if (timeout == 0)
+               timeout = default_timeout;
+
+       /* Never idle if active, or when VBUS timeout is not set as host */
+       if (musb->is_active || ((musb->a_wait_bcon == 0)
+                       && (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) {
+               DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
+               del_timer(&musb_idle_timer);
+               last_timer = jiffies;
+               return;
+       }
+
+       if (time_after(last_timer, timeout)) {
+               if (!timer_pending(&musb_idle_timer))
+                       last_timer = timeout;
+               else {
+                       DBG(4, "Longer idle timer already pending, ignoring\n");
+                       return;
+               }
+       }
+       last_timer = timeout;
+
+       DBG(4, "%s inactive, for idle timer for %lu ms\n",
+               otg_state_string(musb),
+               (unsigned long)jiffies_to_msecs(timeout - jiffies));
+       mod_timer(&musb_idle_timer, timeout);
+}
+
+void musb_platform_enable(struct musb *musb)
+{
+}
+void musb_platform_disable(struct musb *musb)
+{
+}
+static void omap_vbus_power(struct musb *musb, int is_on, int sleeping)
+{
+}
+
+static void omap_set_vbus(struct musb *musb, int is_on)
+{
+       u8              devctl;
+       /* HDRC controls CPEN, but beware current surges during device
+        * connect.  They can trigger transient overcurrent conditions
+        * that must be ignored.
+        */
+
+       devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+       if (is_on) {
+               musb->is_active = 1;
+               musb->xceiv.default_a = 1;
+               musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
+               devctl |= MUSB_DEVCTL_SESSION;
+
+               MUSB_HST_MODE(musb);
+       } else {
+               musb->is_active = 0;
+
+               /* NOTE:  we're skipping A_WAIT_VFALL -> A_IDLE and
+                * jumping right to B_IDLE...
+                */
+
+               musb->xceiv.default_a = 0;
+               musb->xceiv.state = OTG_STATE_B_IDLE;
+               devctl &= ~MUSB_DEVCTL_SESSION;
+
+               MUSB_DEV_MODE(musb);
+       }
+       musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+       DBG(1, "VBUS %s, devctl %02x "
+               /* otg %3x conf %08x prcm %08x */ "\n",
+               otg_state_string(musb),
+               musb_readb(musb->mregs, MUSB_DEVCTL));
+}
+static int omap_set_power(struct otg_transceiver *x, unsigned mA)
+{
+       return 0;
+}
+
+static int musb_platform_resume(struct musb *musb);
+
+void musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+{
+       u8      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+       devctl |= MUSB_DEVCTL_SESSION;
+       musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+       switch (musb_mode) {
+       case MUSB_HOST:
+               otg_set_host(&musb->xceiv, musb->xceiv.host);
+               break;
+       case MUSB_PERIPHERAL:
+               otg_set_peripheral(&musb->xceiv, musb->xceiv.gadget);
+               break;
+       case MUSB_OTG:
+               break;
+       }
+}
+
+int __init musb_platform_init(struct musb *musb)
+{
+       u32 l;
+
+#if defined(CONFIG_ARCH_OMAP2430)
+       omap_cfg_reg(AE5_2430_USB0HS_STP);
+#endif
+
+       musb_platform_resume(musb);
+
+       l = omap_readl(OTG_SYSCONFIG);
+       l &= ~ENABLEWAKEUP;     /* disable wakeup */
+       l &= ~NOSTDBY;          /* remove possible nostdby */
+       l |= SMARTSTDBY;        /* enable smart standby */
+       l &= ~AUTOIDLE;         /* disable auto idle */
+       l &= ~NOIDLE;           /* remove possible noidle */
+       l |= SMARTIDLE;         /* enable smart idle */
+       l |= AUTOIDLE;          /* enable auto idle */
+       omap_writel(l, OTG_SYSCONFIG);
+
+       l = omap_readl(OTG_INTERFSEL);
+       l |= ULPI_12PIN;
+       omap_writel(l, OTG_INTERFSEL);
+
+       pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
+                       "sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
+                       omap_readl(OTG_REVISION), omap_readl(OTG_SYSCONFIG),
+                       omap_readl(OTG_SYSSTATUS), omap_readl(OTG_INTERFSEL),
+                       omap_readl(OTG_SIMENABLE));
+
+       omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
+
+       if (is_host_enabled(musb))
+               musb->board_set_vbus = omap_set_vbus;
+       if (is_peripheral_enabled(musb))
+               musb->xceiv.set_power = omap_set_power;
+       musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON;
+
+       setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
+
+       return 0;
+}
+
+int musb_platform_suspend(struct musb *musb)
+{
+       u32 l;
+
+       if (!musb->clock)
+               return 0;
+
+       /* in any role */
+       l = omap_readl(OTG_FORCESTDBY);
+       l |= ENABLEFORCE;       /* enable MSTANDBY */
+       omap_writel(l, OTG_FORCESTDBY);
+
+       l = omap_readl(OTG_SYSCONFIG);
+       l |= ENABLEWAKEUP;      /* enable wakeup */
+       omap_writel(l, OTG_SYSCONFIG);
+
+       if (musb->xceiv.set_suspend)
+               musb->xceiv.set_suspend(&musb->xceiv, 1);
+
+       if (musb->set_clock)
+               musb->set_clock(musb->clock, 0);
+       else
+               clk_disable(musb->clock);
+
+       return 0;
+}
+
+static int musb_platform_resume(struct musb *musb)
+{
+       u32 l;
+
+       if (!musb->clock)
+               return 0;
+
+       if (musb->xceiv.set_suspend)
+               musb->xceiv.set_suspend(&musb->xceiv, 0);
+
+       if (musb->set_clock)
+               musb->set_clock(musb->clock, 1);
+       else
+               clk_enable(musb->clock);
+
+       l = omap_readl(OTG_SYSCONFIG);
+       l &= ~ENABLEWAKEUP;     /* disable wakeup */
+       omap_writel(l, OTG_SYSCONFIG);
+
+       l = omap_readl(OTG_FORCESTDBY);
+       l &= ~ENABLEFORCE;      /* disable MSTANDBY */
+       omap_writel(l, OTG_FORCESTDBY);
+
+       return 0;
+}
+
+
+int musb_platform_exit(struct musb *musb)
+{
+
+       omap_vbus_power(musb, 0 /*off*/, 1);
+
+       musb_platform_suspend(musb);
+
+       clk_put(musb->clock);
+       musb->clock = 0;
+
+       return 0;
+}
diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h
new file mode 100644 (file)
index 0000000..786a620
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2005-2006 by Texas Instruments
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ */
+
+#ifndef __MUSB_OMAP243X_H__
+#define __MUSB_OMAP243X_H__
+
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+#include <asm/arch/hardware.h>
+#include <asm/arch/usb.h>
+
+/*
+ * OMAP2430-specific definitions
+ */
+
+#define MENTOR_BASE_OFFSET     0
+#if    defined(CONFIG_ARCH_OMAP2430)
+#define        OMAP_HSOTG_BASE         (OMAP243X_HS_BASE)
+#elif  defined(CONFIG_ARCH_OMAP3430)
+#define        OMAP_HSOTG_BASE         (OMAP34XX_HSUSB_OTG_BASE)
+#endif
+#define OMAP_HSOTG(offset)     (OMAP_HSOTG_BASE + 0x400 + (offset))
+#define OTG_REVISION           OMAP_HSOTG(0x0)
+#define OTG_SYSCONFIG          OMAP_HSOTG(0x4)
+#      define  MIDLEMODE       12      /* bit position */
+#      define  FORCESTDBY              (0 << MIDLEMODE)
+#      define  NOSTDBY                 (1 << MIDLEMODE)
+#      define  SMARTSTDBY              (2 << MIDLEMODE)
+#      define  SIDLEMODE               3       /* bit position */
+#      define  FORCEIDLE               (0 << SIDLEMODE)
+#      define  NOIDLE                  (1 << SIDLEMODE)
+#      define  SMARTIDLE               (2 << SIDLEMODE)
+#      define  ENABLEWAKEUP            (1 << 2)
+#      define  SOFTRST                 (1 << 1)
+#      define  AUTOIDLE                (1 << 0)
+#define OTG_SYSSTATUS          OMAP_HSOTG(0x8)
+#      define  RESETDONE               (1 << 0)
+#define OTG_INTERFSEL          OMAP_HSOTG(0xc)
+#      define  EXTCP                   (1 << 2)
+#      define  PHYSEL          0       /* bit position */
+#      define  UTMI_8BIT               (0 << PHYSEL)
+#      define  ULPI_12PIN              (1 << PHYSEL)
+#      define  ULPI_8PIN               (2 << PHYSEL)
+#define OTG_SIMENABLE          OMAP_HSOTG(0x10)
+#      define  TM1                     (1 << 0)
+#define OTG_FORCESTDBY         OMAP_HSOTG(0x14)
+#      define  ENABLEFORCE             (1 << 0)
+
+#endif /* CONFIG_ARCH_OMAP2430 */
+
+#endif /* __MUSB_OMAP243X_H__ */
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
new file mode 100644 (file)
index 0000000..b73b036
--- /dev/null
@@ -0,0 +1,1151 @@
+/*
+ * TUSB6010 USB 2.0 OTG Dual Role controller
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Jarkko Nikula <jarkko.nikula@nokia.com>
+ * Tony Lindgren <tony@atomide.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.
+ *
+ * Notes:
+ * - Driver assumes that interface to external host (main CPU) is
+ *   configured for NOR FLASH interface instead of VLYNQ serial
+ *   interface.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+
+#include "musb_core.h"
+
+static void tusb_source_power(struct musb *musb, int is_on);
+
+#define TUSB_REV_MAJOR(reg_val)                ((reg_val >> 4) & 0xf)
+#define TUSB_REV_MINOR(reg_val)                (reg_val & 0xf)
+
+/*
+ * Checks the revision. We need to use the DMA register as 3.0 does not
+ * have correct versions for TUSB_PRCM_REV or TUSB_INT_CTRL_REV.
+ */
+u8 tusb_get_revision(struct musb *musb)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+       u32             die_id;
+       u8              rev;
+
+       rev = musb_readl(tbase, TUSB_DMA_CTRL_REV) & 0xff;
+       if (TUSB_REV_MAJOR(rev) == 3) {
+               die_id = TUSB_DIDR1_HI_CHIP_REV(musb_readl(tbase,
+                               TUSB_DIDR1_HI));
+               if (die_id >= TUSB_DIDR1_HI_REV_31)
+                       rev |= 1;
+       }
+
+       return rev;
+}
+
+static int __init tusb_print_revision(struct musb *musb)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+       u8              rev;
+
+       rev = tusb_get_revision(musb);
+
+       pr_info("tusb: %s%i.%i %s%i.%i %s%i.%i %s%i.%i %s%i %s%i.%i\n",
+               "prcm",
+               TUSB_REV_MAJOR(musb_readl(tbase, TUSB_PRCM_REV)),
+               TUSB_REV_MINOR(musb_readl(tbase, TUSB_PRCM_REV)),
+               "int",
+               TUSB_REV_MAJOR(musb_readl(tbase, TUSB_INT_CTRL_REV)),
+               TUSB_REV_MINOR(musb_readl(tbase, TUSB_INT_CTRL_REV)),
+               "gpio",
+               TUSB_REV_MAJOR(musb_readl(tbase, TUSB_GPIO_REV)),
+               TUSB_REV_MINOR(musb_readl(tbase, TUSB_GPIO_REV)),
+               "dma",
+               TUSB_REV_MAJOR(musb_readl(tbase, TUSB_DMA_CTRL_REV)),
+               TUSB_REV_MINOR(musb_readl(tbase, TUSB_DMA_CTRL_REV)),
+               "dieid",
+               TUSB_DIDR1_HI_CHIP_REV(musb_readl(tbase, TUSB_DIDR1_HI)),
+               "rev",
+               TUSB_REV_MAJOR(rev), TUSB_REV_MINOR(rev));
+
+       return tusb_get_revision(musb);
+}
+
+#define WBUS_QUIRK_MASK        (TUSB_PHY_OTG_CTRL_TESTM2 | TUSB_PHY_OTG_CTRL_TESTM1 \
+                               | TUSB_PHY_OTG_CTRL_TESTM0)
+
+/*
+ * Workaround for spontaneous WBUS wake-up issue #2 for tusb3.0.
+ * Disables power detection in PHY for the duration of idle.
+ */
+static void tusb_wbus_quirk(struct musb *musb, int enabled)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+       static u32      phy_otg_ctrl, phy_otg_ena;
+       u32             tmp;
+
+       if (enabled) {
+               phy_otg_ctrl = musb_readl(tbase, TUSB_PHY_OTG_CTRL);
+               phy_otg_ena = musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE);
+               tmp = TUSB_PHY_OTG_CTRL_WRPROTECT
+                               | phy_otg_ena | WBUS_QUIRK_MASK;
+               musb_writel(tbase, TUSB_PHY_OTG_CTRL, tmp);
+               tmp = phy_otg_ena & ~WBUS_QUIRK_MASK;
+               tmp |= TUSB_PHY_OTG_CTRL_WRPROTECT | TUSB_PHY_OTG_CTRL_TESTM2;
+               musb_writel(tbase, TUSB_PHY_OTG_CTRL_ENABLE, tmp);
+               DBG(2, "Enabled tusb wbus quirk ctrl %08x ena %08x\n",
+                       musb_readl(tbase, TUSB_PHY_OTG_CTRL),
+                       musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE));
+       } else if (musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE)
+                                       & TUSB_PHY_OTG_CTRL_TESTM2) {
+               tmp = TUSB_PHY_OTG_CTRL_WRPROTECT | phy_otg_ctrl;
+               musb_writel(tbase, TUSB_PHY_OTG_CTRL, tmp);
+               tmp = TUSB_PHY_OTG_CTRL_WRPROTECT | phy_otg_ena;
+               musb_writel(tbase, TUSB_PHY_OTG_CTRL_ENABLE, tmp);
+               DBG(2, "Disabled tusb wbus quirk ctrl %08x ena %08x\n",
+                       musb_readl(tbase, TUSB_PHY_OTG_CTRL),
+                       musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE));
+               phy_otg_ctrl = 0;
+               phy_otg_ena = 0;
+       }
+}
+
+/*
+ * TUSB 6010 may use a parallel bus that doesn't support byte ops;
+ * so both loading and unloading FIFOs need explicit byte counts.
+ */
+
+static inline void
+tusb_fifo_write_unaligned(void __iomem *fifo, const u8 *buf, u16 len)
+{
+       u32             val;
+       int             i;
+
+       if (len > 4) {
+               for (i = 0; i < (len >> 2); i++) {
+                       memcpy(&val, buf, 4);
+                       musb_writel(fifo, 0, val);
+                       buf += 4;
+               }
+               len %= 4;
+       }
+       if (len > 0) {
+               /* Write the rest 1 - 3 bytes to FIFO */
+               memcpy(&val, buf, len);
+               musb_writel(fifo, 0, val);
+       }
+}
+
+static inline void tusb_fifo_read_unaligned(void __iomem *fifo,
+                                               void __iomem *buf, u16 len)
+{
+       u32             val;
+       int             i;
+
+       if (len > 4) {
+               for (i = 0; i < (len >> 2); i++) {
+                       val = musb_readl(fifo, 0);
+                       memcpy(buf, &val, 4);
+                       buf += 4;
+               }
+               len %= 4;
+       }
+       if (len > 0) {
+               /* Read the rest 1 - 3 bytes from FIFO */
+               val = musb_readl(fifo, 0);
+               memcpy(buf, &val, len);
+       }
+}
+
+void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf)
+{
+       void __iomem    *ep_conf = hw_ep->conf;
+       void __iomem    *fifo = hw_ep->fifo;
+       u8              epnum = hw_ep->epnum;
+
+       prefetch(buf);
+
+       DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
+                       'T', epnum, fifo, len, buf);
+
+       if (epnum)
+               musb_writel(ep_conf, TUSB_EP_TX_OFFSET,
+                       TUSB_EP_CONFIG_XFR_SIZE(len));
+       else
+               musb_writel(ep_conf, 0, TUSB_EP0_CONFIG_DIR_TX |
+                       TUSB_EP0_CONFIG_XFR_SIZE(len));
+
+       if (likely((0x01 & (unsigned long) buf) == 0)) {
+
+               /* Best case is 32bit-aligned destination address */
+               if ((0x02 & (unsigned long) buf) == 0) {
+                       if (len >= 4) {
+                               writesl(fifo, buf, len >> 2);
+                               buf += (len & ~0x03);
+                               len &= 0x03;
+                       }
+               } else {
+                       if (len >= 2) {
+                               u32 val;
+                               int i;
+
+                               /* Cannot use writesw, fifo is 32-bit */
+                               for (i = 0; i < (len >> 2); i++) {
+                                       val = (u32)(*(u16 *)buf);
+                                       buf += 2;
+                                       val |= (*(u16 *)buf) << 16;
+                                       buf += 2;
+                                       musb_writel(fifo, 0, val);
+                               }
+                               len &= 0x03;
+                       }
+               }
+       }
+
+       if (len > 0)
+               tusb_fifo_write_unaligned(fifo, buf, len);
+}
+
+void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
+{
+       void __iomem    *ep_conf = hw_ep->conf;
+       void __iomem    *fifo = hw_ep->fifo;
+       u8              epnum = hw_ep->epnum;
+
+       DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
+                       'R', epnum, fifo, len, buf);
+
+       if (epnum)
+               musb_writel(ep_conf, TUSB_EP_RX_OFFSET,
+                       TUSB_EP_CONFIG_XFR_SIZE(len));
+       else
+               musb_writel(ep_conf, 0, TUSB_EP0_CONFIG_XFR_SIZE(len));
+
+       if (likely((0x01 & (unsigned long) buf) == 0)) {
+
+               /* Best case is 32bit-aligned destination address */
+               if ((0x02 & (unsigned long) buf) == 0) {
+                       if (len >= 4) {
+                               readsl(fifo, buf, len >> 2);
+                               buf += (len & ~0x03);
+                               len &= 0x03;
+                       }
+               } else {
+                       if (len >= 2) {
+                               u32 val;
+                               int i;
+
+                               /* Cannot use readsw, fifo is 32-bit */
+                               for (i = 0; i < (len >> 2); i++) {
+                                       val = musb_readl(fifo, 0);
+                                       *(u16 *)buf = (u16)(val & 0xffff);
+                                       buf += 2;
+                                       *(u16 *)buf = (u16)(val >> 16);
+                                       buf += 2;
+                               }
+                               len &= 0x03;
+                       }
+               }
+       }
+
+       if (len > 0)
+               tusb_fifo_read_unaligned(fifo, buf, len);
+}
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+
+/* This is used by gadget drivers, and OTG transceiver logic, allowing
+ * at most mA current to be drawn from VBUS during a Default-B session
+ * (that is, while VBUS exceeds 4.4V).  In Default-A (including pure host
+ * mode), or low power Default-B sessions, something else supplies power.
+ * Caller must take care of locking.
+ */
+static int tusb_draw_power(struct otg_transceiver *x, unsigned mA)
+{
+       struct musb     *musb = container_of(x, struct musb, xceiv);
+       void __iomem    *tbase = musb->ctrl_base;
+       u32             reg;
+
+       /*
+        * Keep clock active when enabled. Note that this is not tied to
+        * drawing VBUS, as with OTG mA can be less than musb->min_power.
+        */
+       if (musb->set_clock) {
+               if (mA)
+                       musb->set_clock(musb->clock, 1);
+               else
+                       musb->set_clock(musb->clock, 0);
+       }
+
+       /* tps65030 seems to consume max 100mA, with maybe 60mA available
+        * (measured on one board) for things other than tps and tusb.
+        *
+        * Boards sharing the CPU clock with CLKIN will need to prevent
+        * certain idle sleep states while the USB link is active.
+        *
+        * REVISIT we could use VBUS to supply only _one_ of { 1.5V, 3.3V }.
+        * The actual current usage would be very board-specific.  For now,
+        * it's simpler to just use an aggregate (also board-specific).
+        */
+       if (x->default_a || mA < (musb->min_power << 1))
+               mA = 0;
+
+       reg = musb_readl(tbase, TUSB_PRCM_MNGMT);
+       if (mA) {
+               musb->is_bus_powered = 1;
+               reg |= TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN;
+       } else {
+               musb->is_bus_powered = 0;
+               reg &= ~(TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN);
+       }
+       musb_writel(tbase, TUSB_PRCM_MNGMT, reg);
+
+       DBG(2, "draw max %d mA VBUS\n", mA);
+       return 0;
+}
+
+#else
+#define tusb_draw_power        NULL
+#endif
+
+/* workaround for issue 13:  change clock during chip idle
+ * (to be fixed in rev3 silicon) ... symptoms include disconnect
+ * or looping suspend/resume cycles
+ */
+static void tusb_set_clock_source(struct musb *musb, unsigned mode)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+       u32             reg;
+
+       reg = musb_readl(tbase, TUSB_PRCM_CONF);
+       reg &= ~TUSB_PRCM_CONF_SYS_CLKSEL(0x3);
+
+       /* 0 = refclk (clkin, XI)
+        * 1 = PHY 60 MHz (internal PLL)
+        * 2 = not supported
+        * 3 = what?
+        */
+       if (mode > 0)
+               reg |= TUSB_PRCM_CONF_SYS_CLKSEL(mode & 0x3);
+
+       musb_writel(tbase, TUSB_PRCM_CONF, reg);
+
+       /* FIXME tusb6010_platform_retime(mode == 0); */
+}
+
+/*
+ * Idle TUSB6010 until next wake-up event; NOR access always wakes.
+ * Other code ensures that we idle unless we're connected _and_ the
+ * USB link is not suspended ... and tells us the relevant wakeup
+ * events.  SW_EN for voltage is handled separately.
+ */
+void tusb_allow_idle(struct musb *musb, u32 wakeup_enables)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+       u32             reg;
+
+       if ((wakeup_enables & TUSB_PRCM_WBUS)
+                       && (tusb_get_revision(musb) == TUSB_REV_30))
+               tusb_wbus_quirk(musb, 1);
+
+       tusb_set_clock_source(musb, 0);
+
+       wakeup_enables |= TUSB_PRCM_WNORCS;
+       musb_writel(tbase, TUSB_PRCM_WAKEUP_MASK, ~wakeup_enables);
+
+       /* REVISIT writeup of WID implies that if WID set and ID is grounded,
+        * TUSB_PHY_OTG_CTRL.TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP must be cleared.
+        * Presumably that's mostly to save power, hence WID is immaterial ...
+        */
+
+       reg = musb_readl(tbase, TUSB_PRCM_MNGMT);
+       /* issue 4: when driving vbus, use hipower (vbus_det) comparator */
+       if (is_host_active(musb)) {
+               reg |= TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN;
+               reg &= ~TUSB_PRCM_MNGMT_OTG_SESS_END_EN;
+       } else {
+               reg |= TUSB_PRCM_MNGMT_OTG_SESS_END_EN;
+               reg &= ~TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN;
+       }
+       reg |= TUSB_PRCM_MNGMT_PM_IDLE | TUSB_PRCM_MNGMT_DEV_IDLE;
+       musb_writel(tbase, TUSB_PRCM_MNGMT, reg);
+
+       DBG(6, "idle, wake on %02x\n", wakeup_enables);
+}
+
+/*
+ * Updates cable VBUS status. Caller must take care of locking.
+ */
+int musb_platform_get_vbus_status(struct musb *musb)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+       u32             otg_stat, prcm_mngmt;
+       int             ret = 0;
+
+       otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
+       prcm_mngmt = musb_readl(tbase, TUSB_PRCM_MNGMT);
+
+       /* Temporarily enable VBUS detection if it was disabled for
+        * suspend mode. Unless it's enabled otg_stat and devctl will
+        * not show correct VBUS state.
+        */
+       if (!(prcm_mngmt & TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN)) {
+               u32 tmp = prcm_mngmt;
+               tmp |= TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN;
+               musb_writel(tbase, TUSB_PRCM_MNGMT, tmp);
+               otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
+               musb_writel(tbase, TUSB_PRCM_MNGMT, prcm_mngmt);
+       }
+
+       if (otg_stat & TUSB_DEV_OTG_STAT_VBUS_VALID)
+               ret = 1;
+
+       return ret;
+}
+
+static struct timer_list musb_idle_timer;
+
+static void musb_do_idle(unsigned long _musb)
+{
+       struct musb     *musb = (void *)_musb;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       switch (musb->xceiv.state) {
+       case OTG_STATE_A_WAIT_BCON:
+               if ((musb->a_wait_bcon != 0)
+                       && (musb->idle_timeout == 0
+                               || time_after(jiffies, musb->idle_timeout))) {
+                       DBG(4, "Nothing connected %s, turning off VBUS\n",
+                                       otg_state_string(musb));
+               }
+               /* FALLTHROUGH */
+       case OTG_STATE_A_IDLE:
+               tusb_source_power(musb, 0);
+       default:
+               break;
+       }
+
+       if (!musb->is_active) {
+               u32     wakeups;
+
+               /* wait until khubd handles port change status */
+               if (is_host_active(musb) && (musb->port1_status >> 16))
+                       goto done;
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+               if (is_peripheral_enabled(musb) && !musb->gadget_driver)
+                       wakeups = 0;
+               else {
+                       wakeups = TUSB_PRCM_WHOSTDISCON
+                                       | TUSB_PRCM_WBUS
+                                       | TUSB_PRCM_WVBUS;
+                       if (is_otg_enabled(musb))
+                               wakeups |= TUSB_PRCM_WID;
+               }
+#else
+               wakeups = TUSB_PRCM_WHOSTDISCON | TUSB_PRCM_WBUS;
+#endif
+               tusb_allow_idle(musb, wakeups);
+       }
+done:
+       spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+/*
+ * Maybe put TUSB6010 into idle mode mode depending on USB link status,
+ * like "disconnected" or "suspended".  We'll be woken out of it by
+ * connect, resume, or disconnect.
+ *
+ * Needs to be called as the last function everywhere where there is
+ * register access to TUSB6010 because of NOR flash wake-up.
+ * Caller should own controller spinlock.
+ *
+ * Delay because peripheral enables D+ pullup 3msec after SE0, and
+ * we don't want to treat that full speed J as a wakeup event.
+ * ... peripherals must draw only suspend current after 10 msec.
+ */
+void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+{
+       unsigned long           default_timeout = jiffies + msecs_to_jiffies(3);
+       static unsigned long    last_timer;
+
+       if (timeout == 0)
+               timeout = default_timeout;
+
+       /* Never idle if active, or when VBUS timeout is not set as host */
+       if (musb->is_active || ((musb->a_wait_bcon == 0)
+                       && (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) {
+               DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
+               del_timer(&musb_idle_timer);
+               last_timer = jiffies;
+               return;
+       }
+
+       if (time_after(last_timer, timeout)) {
+               if (!timer_pending(&musb_idle_timer))
+                       last_timer = timeout;
+               else {
+                       DBG(4, "Longer idle timer already pending, ignoring\n");
+                       return;
+               }
+       }
+       last_timer = timeout;
+
+       DBG(4, "%s inactive, for idle timer for %lu ms\n",
+               otg_state_string(musb),
+               (unsigned long)jiffies_to_msecs(timeout - jiffies));
+       mod_timer(&musb_idle_timer, timeout);
+}
+
+/* ticks of 60 MHz clock */
+#define DEVCLOCK               60000000
+#define OTG_TIMER_MS(msecs)    ((msecs) \
+               ? (TUSB_DEV_OTG_TIMER_VAL((DEVCLOCK/1000)*(msecs)) \
+                               | TUSB_DEV_OTG_TIMER_ENABLE) \
+               : 0)
+
+static void tusb_source_power(struct musb *musb, int is_on)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+       u32             conf, prcm, timer;
+       u8              devctl;
+
+       /* HDRC controls CPEN, but beware current surges during device
+        * connect.  They can trigger transient overcurrent conditions
+        * that must be ignored.
+        */
+
+       prcm = musb_readl(tbase, TUSB_PRCM_MNGMT);
+       conf = musb_readl(tbase, TUSB_DEV_CONF);
+       devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+       if (is_on) {
+               if (musb->set_clock)
+                       musb->set_clock(musb->clock, 1);
+               timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE);
+               musb->xceiv.default_a = 1;
+               musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
+               devctl |= MUSB_DEVCTL_SESSION;
+
+               conf |= TUSB_DEV_CONF_USB_HOST_MODE;
+               MUSB_HST_MODE(musb);
+       } else {
+               u32     otg_stat;
+
+               timer = 0;
+
+               /* If ID pin is grounded, we want to be a_idle */
+               otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
+               if (!(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) {
+                       switch (musb->xceiv.state) {
+                       case OTG_STATE_A_WAIT_VRISE:
+                       case OTG_STATE_A_WAIT_BCON:
+                               musb->xceiv.state = OTG_STATE_A_WAIT_VFALL;
+                               break;
+                       case OTG_STATE_A_WAIT_VFALL:
+                               musb->xceiv.state = OTG_STATE_A_IDLE;
+                               break;
+                       default:
+                               musb->xceiv.state = OTG_STATE_A_IDLE;
+                       }
+                       musb->is_active = 0;
+                       musb->xceiv.default_a = 1;
+                       MUSB_HST_MODE(musb);
+               } else {
+                       musb->is_active = 0;
+                       musb->xceiv.default_a = 0;
+                       musb->xceiv.state = OTG_STATE_B_IDLE;
+                       MUSB_DEV_MODE(musb);
+               }
+
+               devctl &= ~MUSB_DEVCTL_SESSION;
+               conf &= ~TUSB_DEV_CONF_USB_HOST_MODE;
+               if (musb->set_clock)
+                       musb->set_clock(musb->clock, 0);
+       }
+       prcm &= ~(TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN);
+
+       musb_writel(tbase, TUSB_PRCM_MNGMT, prcm);
+       musb_writel(tbase, TUSB_DEV_OTG_TIMER, timer);
+       musb_writel(tbase, TUSB_DEV_CONF, conf);
+       musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+       DBG(1, "VBUS %s, devctl %02x otg %3x conf %08x prcm %08x\n",
+               otg_state_string(musb),
+               musb_readb(musb->mregs, MUSB_DEVCTL),
+               musb_readl(tbase, TUSB_DEV_OTG_STAT),
+               conf, prcm);
+}
+
+/*
+ * Sets the mode to OTG, peripheral or host by changing the ID detection.
+ * Caller must take care of locking.
+ *
+ * Note that if a mini-A cable is plugged in the ID line will stay down as
+ * the weak ID pull-up is not able to pull the ID up.
+ *
+ * REVISIT: It would be possible to add support for changing between host
+ * and peripheral modes in non-OTG configurations by reconfiguring hardware
+ * and then setting musb->board_mode. For now, only support OTG mode.
+ */
+void musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+       u32             otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf;
+
+       if (musb->board_mode != MUSB_OTG) {
+               ERR("Changing mode currently only supported in OTG mode\n");
+               return;
+       }
+
+       otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
+       phy_otg_ctrl = musb_readl(tbase, TUSB_PHY_OTG_CTRL);
+       phy_otg_ena = musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE);
+       dev_conf = musb_readl(tbase, TUSB_DEV_CONF);
+
+       switch (musb_mode) {
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+       case MUSB_HOST:         /* Disable PHY ID detect, ground ID */
+               phy_otg_ctrl &= ~TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
+               phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
+               dev_conf |= TUSB_DEV_CONF_ID_SEL;
+               dev_conf &= ~TUSB_DEV_CONF_SOFT_ID;
+               break;
+#endif
+
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+       case MUSB_PERIPHERAL:   /* Disable PHY ID detect, keep ID pull-up on */
+               phy_otg_ctrl |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
+               phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
+               dev_conf |= (TUSB_DEV_CONF_ID_SEL | TUSB_DEV_CONF_SOFT_ID);
+               break;
+#endif
+
+#ifdef CONFIG_USB_MUSB_OTG
+       case MUSB_OTG:          /* Use PHY ID detection */
+               phy_otg_ctrl |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
+               phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
+               dev_conf &= ~(TUSB_DEV_CONF_ID_SEL | TUSB_DEV_CONF_SOFT_ID);
+               break;
+#endif
+
+       default:
+               DBG(2, "Trying to set unknown mode %i\n", musb_mode);
+       }
+
+       musb_writel(tbase, TUSB_PHY_OTG_CTRL,
+                       TUSB_PHY_OTG_CTRL_WRPROTECT | phy_otg_ctrl);
+       musb_writel(tbase, TUSB_PHY_OTG_CTRL_ENABLE,
+                       TUSB_PHY_OTG_CTRL_WRPROTECT | phy_otg_ena);
+       musb_writel(tbase, TUSB_DEV_CONF, dev_conf);
+
+       otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
+       if ((musb_mode == MUSB_PERIPHERAL) &&
+               !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS))
+                       INFO("Cannot be peripheral with mini-A cable "
+                       "otg_stat: %08x\n", otg_stat);
+}
+
+static inline unsigned long
+tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
+{
+       u32             otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
+       unsigned long   idle_timeout = 0;
+
+       /* ID pin */
+       if ((int_src & TUSB_INT_SRC_ID_STATUS_CHNG)) {
+               int     default_a;
+
+               if (is_otg_enabled(musb))
+                       default_a = !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS);
+               else
+                       default_a = is_host_enabled(musb);
+               DBG(2, "Default-%c\n", default_a ? 'A' : 'B');
+               musb->xceiv.default_a = default_a;
+               tusb_source_power(musb, default_a);
+
+               /* Don't allow idling immediately */
+               if (default_a)
+                       idle_timeout = jiffies + (HZ * 3);
+       }
+
+       /* VBUS state change */
+       if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) {
+
+               /* B-dev state machine:  no vbus ~= disconnect */
+               if ((is_otg_enabled(musb) && !musb->xceiv.default_a)
+                               || !is_host_enabled(musb)) {
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+                       /* ? musb_root_disconnect(musb); */
+                       musb->port1_status &=
+                               ~(USB_PORT_STAT_CONNECTION
+                               | USB_PORT_STAT_ENABLE
+                               | USB_PORT_STAT_LOW_SPEED
+                               | USB_PORT_STAT_HIGH_SPEED
+                               | USB_PORT_STAT_TEST
+                               );
+#endif
+
+                       if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) {
+                               DBG(1, "Forcing disconnect (no interrupt)\n");
+                               if (musb->xceiv.state != OTG_STATE_B_IDLE) {
+                                       /* INTR_DISCONNECT can hide... */
+                                       musb->xceiv.state = OTG_STATE_B_IDLE;
+                                       musb->int_usb |= MUSB_INTR_DISCONNECT;
+                               }
+                               musb->is_active = 0;
+                       }
+                       DBG(2, "vbus change, %s, otg %03x\n",
+                               otg_state_string(musb), otg_stat);
+                       idle_timeout = jiffies + (1 * HZ);
+                       schedule_work(&musb->irq_work);
+
+               } else /* A-dev state machine */ {
+                       DBG(2, "vbus change, %s, otg %03x\n",
+                               otg_state_string(musb), otg_stat);
+
+                       switch (musb->xceiv.state) {
+                       case OTG_STATE_A_IDLE:
+                               DBG(2, "Got SRP, turning on VBUS\n");
+                               musb_set_vbus(musb, 1);
+
+                               /* CONNECT can wake if a_wait_bcon is set */
+                               if (musb->a_wait_bcon != 0)
+                                       musb->is_active = 0;
+                               else
+                                       musb->is_active = 1;
+
+                               /*
+                                * OPT FS A TD.4.6 needs few seconds for
+                                * A_WAIT_VRISE
+                                */
+                               idle_timeout = jiffies + (2 * HZ);
+
+                               break;
+                       case OTG_STATE_A_WAIT_VRISE:
+                               /* ignore; A-session-valid < VBUS_VALID/2,
+                                * we monitor this with the timer
+                                */
+                               break;
+                       case OTG_STATE_A_WAIT_VFALL:
+                               /* REVISIT this irq triggers during short
+                                * spikes caused by enumeration ...
+                                */
+                               if (musb->vbuserr_retry) {
+                                       musb->vbuserr_retry--;
+                                       tusb_source_power(musb, 1);
+                               } else {
+                                       musb->vbuserr_retry
+                                               = VBUSERR_RETRY_COUNT;
+                                       tusb_source_power(musb, 0);
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       /* OTG timer expiration */
+       if (int_src & TUSB_INT_SRC_OTG_TIMEOUT) {
+               u8      devctl;
+
+               DBG(4, "%s timer, %03x\n", otg_state_string(musb), otg_stat);
+
+               switch (musb->xceiv.state) {
+               case OTG_STATE_A_WAIT_VRISE:
+                       /* VBUS has probably been valid for a while now,
+                        * but may well have bounced out of range a bit
+                        */
+                       devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+                       if (otg_stat & TUSB_DEV_OTG_STAT_VBUS_VALID) {
+                               if ((devctl & MUSB_DEVCTL_VBUS)
+                                               != MUSB_DEVCTL_VBUS) {
+                                       DBG(2, "devctl %02x\n", devctl);
+                                       break;
+                               }
+                               musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
+                               musb->is_active = 0;
+                               idle_timeout = jiffies
+                                       + msecs_to_jiffies(musb->a_wait_bcon);
+                       } else {
+                               /* REVISIT report overcurrent to hub? */
+                               ERR("vbus too slow, devctl %02x\n", devctl);
+                               tusb_source_power(musb, 0);
+                       }
+                       break;
+               case OTG_STATE_A_WAIT_BCON:
+                       if (musb->a_wait_bcon != 0)
+                               idle_timeout = jiffies
+                                       + msecs_to_jiffies(musb->a_wait_bcon);
+                       break;
+               case OTG_STATE_A_SUSPEND:
+                       break;
+               case OTG_STATE_B_WAIT_ACON:
+                       break;
+               default:
+                       break;
+               }
+       }
+       schedule_work(&musb->irq_work);
+
+       return idle_timeout;
+}
+
+static irqreturn_t tusb_interrupt(int irq, void *__hci)
+{
+       struct musb     *musb = __hci;
+       void __iomem    *tbase = musb->ctrl_base;
+       unsigned long   flags, idle_timeout = 0;
+       u32             int_mask, int_src;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       /* Mask all interrupts to allow using both edge and level GPIO irq */
+       int_mask = musb_readl(tbase, TUSB_INT_MASK);
+       musb_writel(tbase, TUSB_INT_MASK, ~TUSB_INT_MASK_RESERVED_BITS);
+
+       int_src = musb_readl(tbase, TUSB_INT_SRC) & ~TUSB_INT_SRC_RESERVED_BITS;
+       DBG(3, "TUSB IRQ %08x\n", int_src);
+
+       musb->int_usb = (u8) int_src;
+
+       /* Acknowledge wake-up source interrupts */
+       if (int_src & TUSB_INT_SRC_DEV_WAKEUP) {
+               u32     reg;
+               u32     i;
+
+               if (tusb_get_revision(musb) == TUSB_REV_30)
+                       tusb_wbus_quirk(musb, 0);
+
+               /* there are issues re-locking the PLL on wakeup ... */
+
+               /* work around issue 8 */
+               for (i = 0xf7f7f7; i > 0xf7f7f7 - 1000; i--) {
+                       musb_writel(tbase, TUSB_SCRATCH_PAD, 0);
+                       musb_writel(tbase, TUSB_SCRATCH_PAD, i);
+                       reg = musb_readl(tbase, TUSB_SCRATCH_PAD);
+                       if (reg == i)
+                               break;
+                       DBG(6, "TUSB NOR not ready\n");
+               }
+
+               /* work around issue 13 (2nd half) */
+               tusb_set_clock_source(musb, 1);
+
+               reg = musb_readl(tbase, TUSB_PRCM_WAKEUP_SOURCE);
+               musb_writel(tbase, TUSB_PRCM_WAKEUP_CLEAR, reg);
+               if (reg & ~TUSB_PRCM_WNORCS) {
+                       musb->is_active = 1;
+                       schedule_work(&musb->irq_work);
+               }
+               DBG(3, "wake %sactive %02x\n",
+                               musb->is_active ? "" : "in", reg);
+
+               /* REVISIT host side TUSB_PRCM_WHOSTDISCON, TUSB_PRCM_WBUS */
+       }
+
+       if (int_src & TUSB_INT_SRC_USB_IP_CONN)
+               del_timer(&musb_idle_timer);
+
+       /* OTG state change reports (annoyingly) not issued by Mentor core */
+       if (int_src & (TUSB_INT_SRC_VBUS_SENSE_CHNG
+                               | TUSB_INT_SRC_OTG_TIMEOUT
+                               | TUSB_INT_SRC_ID_STATUS_CHNG))
+               idle_timeout = tusb_otg_ints(musb, int_src, tbase);
+
+       /* TX dma callback must be handled here, RX dma callback is
+        * handled in tusb_omap_dma_cb.
+        */
+       if ((int_src & TUSB_INT_SRC_TXRX_DMA_DONE)) {
+               u32     dma_src = musb_readl(tbase, TUSB_DMA_INT_SRC);
+               u32     real_dma_src = musb_readl(tbase, TUSB_DMA_INT_MASK);
+
+               DBG(3, "DMA IRQ %08x\n", dma_src);
+               real_dma_src = ~real_dma_src & dma_src;
+               if (tusb_dma_omap() && real_dma_src) {
+                       int     tx_source = (real_dma_src & 0xffff);
+                       int     i;
+
+                       for (i = 1; i <= 15; i++) {
+                               if (tx_source & (1 << i)) {
+                                       DBG(3, "completing ep%i %s\n", i, "tx");
+                                       musb_dma_completion(musb, i, 1);
+                               }
+                       }
+               }
+               musb_writel(tbase, TUSB_DMA_INT_CLEAR, dma_src);
+       }
+
+       /* EP interrupts. In OCP mode tusb6010 mirrors the MUSB interrupts */
+       if (int_src & (TUSB_INT_SRC_USB_IP_TX | TUSB_INT_SRC_USB_IP_RX)) {
+               u32     musb_src = musb_readl(tbase, TUSB_USBIP_INT_SRC);
+
+               musb_writel(tbase, TUSB_USBIP_INT_CLEAR, musb_src);
+               musb->int_rx = (((musb_src >> 16) & 0xffff) << 1);
+               musb->int_tx = (musb_src & 0xffff);
+       } else {
+               musb->int_rx = 0;
+               musb->int_tx = 0;
+       }
+
+       if (int_src & (TUSB_INT_SRC_USB_IP_TX | TUSB_INT_SRC_USB_IP_RX | 0xff))
+               musb_interrupt(musb);
+
+       /* Acknowledge TUSB interrupts. Clear only non-reserved bits */
+       musb_writel(tbase, TUSB_INT_SRC_CLEAR,
+               int_src & ~TUSB_INT_MASK_RESERVED_BITS);
+
+       musb_platform_try_idle(musb, idle_timeout);
+
+       musb_writel(tbase, TUSB_INT_MASK, int_mask);
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+static int dma_off;
+
+/*
+ * Enables TUSB6010. Caller must take care of locking.
+ * REVISIT:
+ * - Check what is unnecessary in MGC_HdrcStart()
+ */
+void musb_platform_enable(struct musb *musb)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+
+       /* Setup TUSB6010 main interrupt mask. Enable all interrupts except SOF.
+        * REVISIT: Enable and deal with TUSB_INT_SRC_USB_IP_SOF */
+       musb_writel(tbase, TUSB_INT_MASK, TUSB_INT_SRC_USB_IP_SOF);
+
+       /* Setup TUSB interrupt, disable DMA and GPIO interrupts */
+       musb_writel(tbase, TUSB_USBIP_INT_MASK, 0);
+       musb_writel(tbase, TUSB_DMA_INT_MASK, 0x7fffffff);
+       musb_writel(tbase, TUSB_GPIO_INT_MASK, 0x1ff);
+
+       /* Clear all subsystem interrups */
+       musb_writel(tbase, TUSB_USBIP_INT_CLEAR, 0x7fffffff);
+       musb_writel(tbase, TUSB_DMA_INT_CLEAR, 0x7fffffff);
+       musb_writel(tbase, TUSB_GPIO_INT_CLEAR, 0x1ff);
+
+       /* Acknowledge pending interrupt(s) */
+       musb_writel(tbase, TUSB_INT_SRC_CLEAR, ~TUSB_INT_MASK_RESERVED_BITS);
+
+       /* Only 0 clock cycles for minimum interrupt de-assertion time and
+        * interrupt polarity active low seems to work reliably here */
+       musb_writel(tbase, TUSB_INT_CTRL_CONF,
+                       TUSB_INT_CTRL_CONF_INT_RELCYC(0));
+
+       set_irq_type(musb->nIrq, IRQ_TYPE_LEVEL_LOW);
+
+       /* maybe force into the Default-A OTG state machine */
+       if (!(musb_readl(tbase, TUSB_DEV_OTG_STAT)
+                       & TUSB_DEV_OTG_STAT_ID_STATUS))
+               musb_writel(tbase, TUSB_INT_SRC_SET,
+                               TUSB_INT_SRC_ID_STATUS_CHNG);
+
+       if (is_dma_capable() && dma_off)
+               printk(KERN_WARNING "%s %s: dma not reactivated\n",
+                               __FILE__, __func__);
+       else
+               dma_off = 1;
+}
+
+/*
+ * Disables TUSB6010. Caller must take care of locking.
+ */
+void musb_platform_disable(struct musb *musb)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+
+       /* FIXME stop DMA, IRQs, timers, ... */
+
+       /* disable all IRQs */
+       musb_writel(tbase, TUSB_INT_MASK, ~TUSB_INT_MASK_RESERVED_BITS);
+       musb_writel(tbase, TUSB_USBIP_INT_MASK, 0x7fffffff);
+       musb_writel(tbase, TUSB_DMA_INT_MASK, 0x7fffffff);
+       musb_writel(tbase, TUSB_GPIO_INT_MASK, 0x1ff);
+
+       del_timer(&musb_idle_timer);
+
+       if (is_dma_capable() && !dma_off) {
+               printk(KERN_WARNING "%s %s: dma still active\n",
+                               __FILE__, __func__);
+               dma_off = 1;
+       }
+}
+
+/*
+ * Sets up TUSB6010 CPU interface specific signals and registers
+ * Note: Settings optimized for OMAP24xx
+ */
+static void __init tusb_setup_cpu_interface(struct musb *musb)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+
+       /*
+        * Disable GPIO[5:0] pullups (used as output DMA requests)
+        * Don't disable GPIO[7:6] as they are needed for wake-up.
+        */
+       musb_writel(tbase, TUSB_PULLUP_1_CTRL, 0x0000003F);
+
+       /* Disable all pullups on NOR IF, DMAREQ0 and DMAREQ1 */
+       musb_writel(tbase, TUSB_PULLUP_2_CTRL, 0x01FFFFFF);
+
+       /* Turn GPIO[5:0] to DMAREQ[5:0] signals */
+       musb_writel(tbase, TUSB_GPIO_CONF, TUSB_GPIO_CONF_DMAREQ(0x3f));
+
+       /* Burst size 16x16 bits, all six DMA requests enabled, DMA request
+        * de-assertion time 2 system clocks p 62 */
+       musb_writel(tbase, TUSB_DMA_REQ_CONF,
+               TUSB_DMA_REQ_CONF_BURST_SIZE(2) |
+               TUSB_DMA_REQ_CONF_DMA_REQ_EN(0x3f) |
+               TUSB_DMA_REQ_CONF_DMA_REQ_ASSER(2));
+
+       /* Set 0 wait count for synchronous burst access */
+       musb_writel(tbase, TUSB_WAIT_COUNT, 1);
+}
+
+static int __init tusb_start(struct musb *musb)
+{
+       void __iomem    *tbase = musb->ctrl_base;
+       int             ret = 0;
+       unsigned long   flags;
+       u32             reg;
+
+       if (musb->board_set_power)
+               ret = musb->board_set_power(1);
+       if (ret != 0) {
+               printk(KERN_ERR "tusb: Cannot enable TUSB6010\n");
+               return ret;
+       }
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       if (musb_readl(tbase, TUSB_PROD_TEST_RESET) !=
+               TUSB_PROD_TEST_RESET_VAL) {
+               printk(KERN_ERR "tusb: Unable to detect TUSB6010\n");
+               goto err;
+       }
+
+       ret = tusb_print_revision(musb);
+       if (ret < 2) {
+               printk(KERN_ERR "tusb: Unsupported TUSB6010 revision %i\n",
+                               ret);
+               goto err;
+       }
+
+       /* The uint bit for "USB non-PDR interrupt enable" has to be 1 when
+        * NOR FLASH interface is used */
+       musb_writel(tbase, TUSB_VLYNQ_CTRL, 8);
+
+       /* Select PHY free running 60MHz as a system clock */
+       tusb_set_clock_source(musb, 1);
+
+       /* VBus valid timer 1us, disable DFT/Debug and VLYNQ clocks for
+        * power saving, enable VBus detect and session end comparators,
+        * enable IDpullup, enable VBus charging */
+       musb_writel(tbase, TUSB_PRCM_MNGMT,
+               TUSB_PRCM_MNGMT_VBUS_VALID_TIMER(0xa) |
+               TUSB_PRCM_MNGMT_VBUS_VALID_FLT_EN |
+               TUSB_PRCM_MNGMT_OTG_SESS_END_EN |
+               TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN |
+               TUSB_PRCM_MNGMT_OTG_ID_PULLUP);
+       tusb_setup_cpu_interface(musb);
+
+       /* simplify:  always sense/pullup ID pins, as if in OTG mode */
+       reg = musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE);
+       reg |= TUSB_PHY_OTG_CTRL_WRPROTECT | TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
+       musb_writel(tbase, TUSB_PHY_OTG_CTRL_ENABLE, reg);
+
+       reg = musb_readl(tbase, TUSB_PHY_OTG_CTRL);
+       reg |= TUSB_PHY_OTG_CTRL_WRPROTECT | TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
+       musb_writel(tbase, TUSB_PHY_OTG_CTRL, reg);
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       return 0;
+
+err:
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       if (musb->board_set_power)
+               musb->board_set_power(0);
+
+       return -ENODEV;
+}
+
+int __init musb_platform_init(struct musb *musb)
+{
+       struct platform_device  *pdev;
+       struct resource         *mem;
+       void __iomem            *sync;
+       int                     ret;
+
+       pdev = to_platform_device(musb->controller);
+
+       /* dma address for async dma */
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       musb->async = mem->start;
+
+       /* dma address for sync dma */
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!mem) {
+               pr_debug("no sync dma resource?\n");
+               return -ENODEV;
+       }
+       musb->sync = mem->start;
+
+       sync = ioremap(mem->start, mem->end - mem->start + 1);
+       if (!sync) {
+               pr_debug("ioremap for sync failed\n");
+               return -ENOMEM;
+       }
+       musb->sync_va = sync;
+
+       /* Offsets from base: VLYNQ at 0x000, MUSB regs at 0x400,
+        * FIFOs at 0x600, TUSB at 0x800
+        */
+       musb->mregs += TUSB_BASE_OFFSET;
+
+       ret = tusb_start(musb);
+       if (ret) {
+               printk(KERN_ERR "Could not start tusb6010 (%d)\n",
+                               ret);
+               return -ENODEV;
+       }
+       musb->isr = tusb_interrupt;
+
+       if (is_host_enabled(musb))
+               musb->board_set_vbus = tusb_source_power;
+       if (is_peripheral_enabled(musb))
+               musb->xceiv.set_power = tusb_draw_power;
+
+       setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
+
+       return ret;
+}
+
+int musb_platform_exit(struct musb *musb)
+{
+       del_timer_sync(&musb_idle_timer);
+
+       if (musb->board_set_power)
+               musb->board_set_power(0);
+
+       iounmap(musb->sync_va);
+
+       return 0;
+}
diff --git a/drivers/usb/musb/tusb6010.h b/drivers/usb/musb/tusb6010.h
new file mode 100644 (file)
index 0000000..ab8c962
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Definitions for TUSB6010 USB 2.0 OTG Dual Role controller
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Jarkko Nikula <jarkko.nikula@nokia.com>
+ * Tony Lindgren <tony@atomide.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.
+ */
+
+#ifndef __TUSB6010_H__
+#define __TUSB6010_H__
+
+extern u8 tusb_get_revision(struct musb *musb);
+
+#ifdef CONFIG_USB_TUSB6010
+#define musb_in_tusb()                 1
+#else
+#define musb_in_tusb()                 0
+#endif
+
+#ifdef CONFIG_USB_TUSB_OMAP_DMA
+#define tusb_dma_omap()                        1
+#else
+#define tusb_dma_omap()                        0
+#endif
+
+/* VLYNQ control register. 32-bit at offset 0x000 */
+#define TUSB_VLYNQ_CTRL                        0x004
+
+/* Mentor Graphics OTG core registers. 8,- 16- and 32-bit at offset 0x400 */
+#define TUSB_BASE_OFFSET               0x400
+
+/* FIFO registers 32-bit at offset 0x600 */
+#define TUSB_FIFO_BASE                 0x600
+
+/* Device System & Control registers. 32-bit at offset 0x800 */
+#define TUSB_SYS_REG_BASE              0x800
+
+#define TUSB_DEV_CONF                  (TUSB_SYS_REG_BASE + 0x000)
+#define                TUSB_DEV_CONF_USB_HOST_MODE             (1 << 16)
+#define                TUSB_DEV_CONF_PROD_TEST_MODE            (1 << 15)
+#define                TUSB_DEV_CONF_SOFT_ID                   (1 << 1)
+#define                TUSB_DEV_CONF_ID_SEL                    (1 << 0)
+
+#define TUSB_PHY_OTG_CTRL_ENABLE       (TUSB_SYS_REG_BASE + 0x004)
+#define TUSB_PHY_OTG_CTRL              (TUSB_SYS_REG_BASE + 0x008)
+#define                TUSB_PHY_OTG_CTRL_WRPROTECT             (0xa5 << 24)
+#define                TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP         (1 << 23)
+#define                TUSB_PHY_OTG_CTRL_OTG_VBUS_DET_EN       (1 << 19)
+#define                TUSB_PHY_OTG_CTRL_OTG_SESS_END_EN       (1 << 18)
+#define                TUSB_PHY_OTG_CTRL_TESTM2                (1 << 17)
+#define                TUSB_PHY_OTG_CTRL_TESTM1                (1 << 16)
+#define                TUSB_PHY_OTG_CTRL_TESTM0                (1 << 15)
+#define                TUSB_PHY_OTG_CTRL_TX_DATA2              (1 << 14)
+#define                TUSB_PHY_OTG_CTRL_TX_GZ2                (1 << 13)
+#define                TUSB_PHY_OTG_CTRL_TX_ENABLE2            (1 << 12)
+#define                TUSB_PHY_OTG_CTRL_DM_PULLDOWN           (1 << 11)
+#define                TUSB_PHY_OTG_CTRL_DP_PULLDOWN           (1 << 10)
+#define                TUSB_PHY_OTG_CTRL_OSC_EN                (1 << 9)
+#define                TUSB_PHY_OTG_CTRL_PHYREF_CLKSEL(v)      (((v) & 3) << 7)
+#define                TUSB_PHY_OTG_CTRL_PD                    (1 << 6)
+#define                TUSB_PHY_OTG_CTRL_PLL_ON                (1 << 5)
+#define                TUSB_PHY_OTG_CTRL_EXT_RPU               (1 << 4)
+#define                TUSB_PHY_OTG_CTRL_PWR_GOOD              (1 << 3)
+#define                TUSB_PHY_OTG_CTRL_RESET                 (1 << 2)
+#define                TUSB_PHY_OTG_CTRL_SUSPENDM              (1 << 1)
+#define                TUSB_PHY_OTG_CTRL_CLK_MODE              (1 << 0)
+
+/*OTG status register */
+#define TUSB_DEV_OTG_STAT              (TUSB_SYS_REG_BASE + 0x00c)
+#define                TUSB_DEV_OTG_STAT_PWR_CLK_GOOD          (1 << 8)
+#define                TUSB_DEV_OTG_STAT_SESS_END              (1 << 7)
+#define                TUSB_DEV_OTG_STAT_SESS_VALID            (1 << 6)
+#define                TUSB_DEV_OTG_STAT_VBUS_VALID            (1 << 5)
+#define                TUSB_DEV_OTG_STAT_VBUS_SENSE            (1 << 4)
+#define                TUSB_DEV_OTG_STAT_ID_STATUS             (1 << 3)
+#define                TUSB_DEV_OTG_STAT_HOST_DISCON           (1 << 2)
+#define                TUSB_DEV_OTG_STAT_LINE_STATE            (3 << 0)
+#define                TUSB_DEV_OTG_STAT_DP_ENABLE             (1 << 1)
+#define                TUSB_DEV_OTG_STAT_DM_ENABLE             (1 << 0)
+
+#define TUSB_DEV_OTG_TIMER             (TUSB_SYS_REG_BASE + 0x010)
+#      define TUSB_DEV_OTG_TIMER_ENABLE                (1 << 31)
+#      define TUSB_DEV_OTG_TIMER_VAL(v)                ((v) & 0x07ffffff)
+#define TUSB_PRCM_REV                  (TUSB_SYS_REG_BASE + 0x014)
+
+/* PRCM configuration register */
+#define TUSB_PRCM_CONF                 (TUSB_SYS_REG_BASE + 0x018)
+#define                TUSB_PRCM_CONF_SFW_CPEN         (1 << 24)
+#define                TUSB_PRCM_CONF_SYS_CLKSEL(v)    (((v) & 3) << 16)
+
+/* PRCM management register */
+#define TUSB_PRCM_MNGMT                        (TUSB_SYS_REG_BASE + 0x01c)
+#define                TUSB_PRCM_MNGMT_SRP_FIX_TIMER(v)        (((v) & 0xf) << 25)
+#define                TUSB_PRCM_MNGMT_SRP_FIX_EN              (1 << 24)
+#define                TUSB_PRCM_MNGMT_VBUS_VALID_TIMER(v)     (((v) & 0xf) << 20)
+#define                TUSB_PRCM_MNGMT_VBUS_VALID_FLT_EN       (1 << 19)
+#define                TUSB_PRCM_MNGMT_DFT_CLK_DIS             (1 << 18)
+#define                TUSB_PRCM_MNGMT_VLYNQ_CLK_DIS           (1 << 17)
+#define                TUSB_PRCM_MNGMT_OTG_SESS_END_EN         (1 << 10)
+#define                TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN         (1 << 9)
+#define                TUSB_PRCM_MNGMT_OTG_ID_PULLUP           (1 << 8)
+#define                TUSB_PRCM_MNGMT_15_SW_EN                (1 << 4)
+#define                TUSB_PRCM_MNGMT_33_SW_EN                (1 << 3)
+#define                TUSB_PRCM_MNGMT_5V_CPEN                 (1 << 2)
+#define                TUSB_PRCM_MNGMT_PM_IDLE                 (1 << 1)
+#define                TUSB_PRCM_MNGMT_DEV_IDLE                (1 << 0)
+
+/* Wake-up source clear and mask registers */
+#define TUSB_PRCM_WAKEUP_SOURCE                (TUSB_SYS_REG_BASE + 0x020)
+#define TUSB_PRCM_WAKEUP_CLEAR         (TUSB_SYS_REG_BASE + 0x028)
+#define TUSB_PRCM_WAKEUP_MASK          (TUSB_SYS_REG_BASE + 0x02c)
+#define                TUSB_PRCM_WAKEUP_RESERVED_BITS  (0xffffe << 13)
+#define                TUSB_PRCM_WGPIO_7       (1 << 12)
+#define                TUSB_PRCM_WGPIO_6       (1 << 11)
+#define                TUSB_PRCM_WGPIO_5       (1 << 10)
+#define                TUSB_PRCM_WGPIO_4       (1 << 9)
+#define                TUSB_PRCM_WGPIO_3       (1 << 8)
+#define                TUSB_PRCM_WGPIO_2       (1 << 7)
+#define                TUSB_PRCM_WGPIO_1       (1 << 6)
+#define                TUSB_PRCM_WGPIO_0       (1 << 5)
+#define                TUSB_PRCM_WHOSTDISCON   (1 << 4)        /* Host disconnect */
+#define                TUSB_PRCM_WBUS          (1 << 3)        /* USB bus resume */
+#define                TUSB_PRCM_WNORCS        (1 << 2)        /* NOR chip select */
+#define                TUSB_PRCM_WVBUS         (1 << 1)        /* OTG PHY VBUS */
+#define                TUSB_PRCM_WID           (1 << 0)        /* OTG PHY ID detect */
+
+#define TUSB_PULLUP_1_CTRL             (TUSB_SYS_REG_BASE + 0x030)
+#define TUSB_PULLUP_2_CTRL             (TUSB_SYS_REG_BASE + 0x034)
+#define TUSB_INT_CTRL_REV              (TUSB_SYS_REG_BASE + 0x038)
+#define TUSB_INT_CTRL_CONF             (TUSB_SYS_REG_BASE + 0x03c)
+#define TUSB_USBIP_INT_SRC             (TUSB_SYS_REG_BASE + 0x040)
+#define TUSB_USBIP_INT_SET             (TUSB_SYS_REG_BASE + 0x044)
+#define TUSB_USBIP_INT_CLEAR           (TUSB_SYS_REG_BASE + 0x048)
+#define TUSB_USBIP_INT_MASK            (TUSB_SYS_REG_BASE + 0x04c)
+#define TUSB_DMA_INT_SRC               (TUSB_SYS_REG_BASE + 0x050)
+#define TUSB_DMA_INT_SET               (TUSB_SYS_REG_BASE + 0x054)
+#define TUSB_DMA_INT_CLEAR             (TUSB_SYS_REG_BASE + 0x058)
+#define TUSB_DMA_INT_MASK              (TUSB_SYS_REG_BASE + 0x05c)
+#define TUSB_GPIO_INT_SRC              (TUSB_SYS_REG_BASE + 0x060)
+#define TUSB_GPIO_INT_SET              (TUSB_SYS_REG_BASE + 0x064)
+#define TUSB_GPIO_INT_CLEAR            (TUSB_SYS_REG_BASE + 0x068)
+#define TUSB_GPIO_INT_MASK             (TUSB_SYS_REG_BASE + 0x06c)
+
+/* NOR flash interrupt source registers */
+#define TUSB_INT_SRC                   (TUSB_SYS_REG_BASE + 0x070)
+#define TUSB_INT_SRC_SET               (TUSB_SYS_REG_BASE + 0x074)
+#define TUSB_INT_SRC_CLEAR             (TUSB_SYS_REG_BASE + 0x078)
+#define TUSB_INT_MASK                  (TUSB_SYS_REG_BASE + 0x07c)
+#define                TUSB_INT_SRC_TXRX_DMA_DONE              (1 << 24)
+#define                TUSB_INT_SRC_USB_IP_CORE                (1 << 17)
+#define                TUSB_INT_SRC_OTG_TIMEOUT                (1 << 16)
+#define                TUSB_INT_SRC_VBUS_SENSE_CHNG            (1 << 15)
+#define                TUSB_INT_SRC_ID_STATUS_CHNG             (1 << 14)
+#define                TUSB_INT_SRC_DEV_WAKEUP                 (1 << 13)
+#define                TUSB_INT_SRC_DEV_READY                  (1 << 12)
+#define                TUSB_INT_SRC_USB_IP_TX                  (1 << 9)
+#define                TUSB_INT_SRC_USB_IP_RX                  (1 << 8)
+#define                TUSB_INT_SRC_USB_IP_VBUS_ERR            (1 << 7)
+#define                TUSB_INT_SRC_USB_IP_VBUS_REQ            (1 << 6)
+#define                TUSB_INT_SRC_USB_IP_DISCON              (1 << 5)
+#define                TUSB_INT_SRC_USB_IP_CONN                (1 << 4)
+#define                TUSB_INT_SRC_USB_IP_SOF                 (1 << 3)
+#define                TUSB_INT_SRC_USB_IP_RST_BABBLE          (1 << 2)
+#define                TUSB_INT_SRC_USB_IP_RESUME              (1 << 1)
+#define                TUSB_INT_SRC_USB_IP_SUSPEND             (1 << 0)
+
+/* NOR flash interrupt registers reserved bits. Must be written as 0 */
+#define                TUSB_INT_MASK_RESERVED_17               (0x3fff << 17)
+#define                TUSB_INT_MASK_RESERVED_13               (1 << 13)
+#define                TUSB_INT_MASK_RESERVED_8                (0xf << 8)
+#define                TUSB_INT_SRC_RESERVED_26                (0x1f << 26)
+#define                TUSB_INT_SRC_RESERVED_18                (0x3f << 18)
+#define                TUSB_INT_SRC_RESERVED_10                (0x03 << 10)
+
+/* Reserved bits for NOR flash interrupt mask and clear register */
+#define                TUSB_INT_MASK_RESERVED_BITS     (TUSB_INT_MASK_RESERVED_17 | \
+                                               TUSB_INT_MASK_RESERVED_13 | \
+                                               TUSB_INT_MASK_RESERVED_8)
+
+/* Reserved bits for NOR flash interrupt status register */
+#define                TUSB_INT_SRC_RESERVED_BITS      (TUSB_INT_SRC_RESERVED_26 | \
+                                               TUSB_INT_SRC_RESERVED_18 | \
+                                               TUSB_INT_SRC_RESERVED_10)
+
+#define TUSB_GPIO_REV                  (TUSB_SYS_REG_BASE + 0x080)
+#define TUSB_GPIO_CONF                 (TUSB_SYS_REG_BASE + 0x084)
+#define TUSB_DMA_CTRL_REV              (TUSB_SYS_REG_BASE + 0x100)
+#define TUSB_DMA_REQ_CONF              (TUSB_SYS_REG_BASE + 0x104)
+#define TUSB_EP0_CONF                  (TUSB_SYS_REG_BASE + 0x108)
+#define TUSB_DMA_EP_MAP                        (TUSB_SYS_REG_BASE + 0x148)
+
+/* Offsets from each ep base register */
+#define TUSB_EP_TX_OFFSET              0x10c   /* EP_IN in docs */
+#define TUSB_EP_RX_OFFSET              0x14c   /* EP_OUT in docs */
+#define TUSB_EP_MAX_PACKET_SIZE_OFFSET 0x188
+
+#define TUSB_WAIT_COUNT                        (TUSB_SYS_REG_BASE + 0x1c8)
+#define TUSB_SCRATCH_PAD               (TUSB_SYS_REG_BASE + 0x1c4)
+#define TUSB_PROD_TEST_RESET           (TUSB_SYS_REG_BASE + 0x1d8)
+
+/* Device System & Control register bitfields */
+#define TUSB_INT_CTRL_CONF_INT_RELCYC(v)       (((v) & 0x7) << 18)
+#define TUSB_INT_CTRL_CONF_INT_POLARITY                (1 << 17)
+#define TUSB_INT_CTRL_CONF_INT_MODE            (1 << 16)
+#define TUSB_GPIO_CONF_DMAREQ(v)               (((v) & 0x3f) << 24)
+#define TUSB_DMA_REQ_CONF_BURST_SIZE(v)                (((v) & 3) << 26)
+#define TUSB_DMA_REQ_CONF_DMA_REQ_EN(v)                (((v) & 0x3f) << 20)
+#define TUSB_DMA_REQ_CONF_DMA_REQ_ASSER(v)     (((v) & 0xf) << 16)
+#define TUSB_EP0_CONFIG_SW_EN                  (1 << 8)
+#define TUSB_EP0_CONFIG_DIR_TX                 (1 << 7)
+#define TUSB_EP0_CONFIG_XFR_SIZE(v)            ((v) & 0x7f)
+#define TUSB_EP_CONFIG_SW_EN                   (1 << 31)
+#define TUSB_EP_CONFIG_XFR_SIZE(v)             ((v) & 0x7fffffff)
+#define TUSB_PROD_TEST_RESET_VAL               0xa596
+#define TUSB_EP_FIFO(ep)                       (TUSB_FIFO_BASE + (ep) * 0x20)
+
+#define TUSB_DIDR1_LO                          (TUSB_SYS_REG_BASE + 0x1f8)
+#define TUSB_DIDR1_HI                          (TUSB_SYS_REG_BASE + 0x1fc)
+#define                TUSB_DIDR1_HI_CHIP_REV(v)               (((v) >> 17) & 0xf)
+#define                        TUSB_DIDR1_HI_REV_20            0
+#define                        TUSB_DIDR1_HI_REV_30            1
+#define                        TUSB_DIDR1_HI_REV_31            2
+
+#define TUSB_REV_10    0x10
+#define TUSB_REV_20    0x20
+#define TUSB_REV_30    0x30
+#define TUSB_REV_31    0x31
+
+#endif /* __TUSB6010_H__ */
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
new file mode 100644 (file)
index 0000000..52f7f29
--- /dev/null
@@ -0,0 +1,719 @@
+/*
+ * TUSB6010 USB 2.0 OTG Dual Role controller OMAP DMA interface
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Tony Lindgren <tony@atomide.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/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/mux.h>
+
+#include "musb_core.h"
+
+#define to_chdat(c)            ((struct tusb_omap_dma_ch *)(c)->private_data)
+
+#define MAX_DMAREQ             5       /* REVISIT: Really 6, but req5 not OK */
+
+struct tusb_omap_dma_ch {
+       struct musb             *musb;
+       void __iomem            *tbase;
+       unsigned long           phys_offset;
+       int                     epnum;
+       u8                      tx;
+       struct musb_hw_ep       *hw_ep;
+
+       int                     ch;
+       s8                      dmareq;
+       s8                      sync_dev;
+
+       struct tusb_omap_dma    *tusb_dma;
+
+       void __iomem            *dma_addr;
+
+       u32                     len;
+       u16                     packet_sz;
+       u16                     transfer_packet_sz;
+       u32                     transfer_len;
+       u32                     completed_len;
+};
+
+struct tusb_omap_dma {
+       struct dma_controller           controller;
+       struct musb                     *musb;
+       void __iomem                    *tbase;
+
+       int                             ch;
+       s8                              dmareq;
+       s8                              sync_dev;
+       unsigned                        multichannel:1;
+};
+
+static int tusb_omap_dma_start(struct dma_controller *c)
+{
+       struct tusb_omap_dma    *tusb_dma;
+
+       tusb_dma = container_of(c, struct tusb_omap_dma, controller);
+
+       /* DBG(3, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */
+
+       return 0;
+}
+
+static int tusb_omap_dma_stop(struct dma_controller *c)
+{
+       struct tusb_omap_dma    *tusb_dma;
+
+       tusb_dma = container_of(c, struct tusb_omap_dma, controller);
+
+       /* DBG(3, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */
+
+       return 0;
+}
+
+/*
+ * Allocate dmareq0 to the current channel unless it's already taken
+ */
+static inline int tusb_omap_use_shared_dmareq(struct tusb_omap_dma_ch *chdat)
+{
+       u32             reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
+
+       if (reg != 0) {
+               DBG(3, "ep%i dmareq0 is busy for ep%i\n",
+                       chdat->epnum, reg & 0xf);
+               return -EAGAIN;
+       }
+
+       if (chdat->tx)
+               reg = (1 << 4) | chdat->epnum;
+       else
+               reg = chdat->epnum;
+
+       musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
+
+       return 0;
+}
+
+static inline void tusb_omap_free_shared_dmareq(struct tusb_omap_dma_ch *chdat)
+{
+       u32             reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
+
+       if ((reg & 0xf) != chdat->epnum) {
+               printk(KERN_ERR "ep%i trying to release dmareq0 for ep%i\n",
+                       chdat->epnum, reg & 0xf);
+               return;
+       }
+       musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, 0);
+}
+
+/*
+ * See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in
+ * musb_gadget.c.
+ */
+static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
+{
+       struct dma_channel      *channel = (struct dma_channel *)data;
+       struct tusb_omap_dma_ch *chdat = to_chdat(channel);
+       struct tusb_omap_dma    *tusb_dma = chdat->tusb_dma;
+       struct musb             *musb = chdat->musb;
+       struct musb_hw_ep       *hw_ep = chdat->hw_ep;
+       void __iomem            *ep_conf = hw_ep->conf;
+       void __iomem            *mbase = musb->mregs;
+       unsigned long           remaining, flags, pio;
+       int                     ch;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       if (tusb_dma->multichannel)
+               ch = chdat->ch;
+       else
+               ch = tusb_dma->ch;
+
+       if (ch_status != OMAP_DMA_BLOCK_IRQ)
+               printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
+
+       DBG(3, "ep%i %s dma callback ch: %i status: %x\n",
+               chdat->epnum, chdat->tx ? "tx" : "rx",
+               ch, ch_status);
+
+       if (chdat->tx)
+               remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
+       else
+               remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET);
+
+       remaining = TUSB_EP_CONFIG_XFR_SIZE(remaining);
+
+       /* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
+       if (unlikely(remaining > chdat->transfer_len)) {
+               DBG(2, "Corrupt %s dma ch%i XFR_SIZE: 0x%08lx\n",
+                       chdat->tx ? "tx" : "rx", chdat->ch,
+                       remaining);
+               remaining = 0;
+       }
+
+       channel->actual_len = chdat->transfer_len - remaining;
+       pio = chdat->len - channel->actual_len;
+
+       DBG(3, "DMA remaining %lu/%u\n", remaining, chdat->transfer_len);
+
+       /* Transfer remaining 1 - 31 bytes */
+       if (pio > 0 && pio < 32) {
+               u8      *buf;
+
+               DBG(3, "Using PIO for remaining %lu bytes\n", pio);
+               buf = phys_to_virt((u32)chdat->dma_addr) + chdat->transfer_len;
+               if (chdat->tx) {
+                       dma_cache_maint(phys_to_virt((u32)chdat->dma_addr),
+                                       chdat->transfer_len, DMA_TO_DEVICE);
+                       musb_write_fifo(hw_ep, pio, buf);
+               } else {
+                       musb_read_fifo(hw_ep, pio, buf);
+                       dma_cache_maint(phys_to_virt((u32)chdat->dma_addr),
+                                       chdat->transfer_len, DMA_FROM_DEVICE);
+               }
+               channel->actual_len += pio;
+       }
+
+       if (!tusb_dma->multichannel)
+               tusb_omap_free_shared_dmareq(chdat);
+
+       channel->status = MUSB_DMA_STATUS_FREE;
+
+       /* Handle only RX callbacks here. TX callbacks must be handled based
+        * on the TUSB DMA status interrupt.
+        * REVISIT: Use both TUSB DMA status interrupt and OMAP DMA callback
+        * interrupt for RX and TX.
+        */
+       if (!chdat->tx)
+               musb_dma_completion(musb, chdat->epnum, chdat->tx);
+
+       /* We must terminate short tx transfers manually by setting TXPKTRDY.
+        * REVISIT: This same problem may occur with other MUSB dma as well.
+        * Easy to test with g_ether by pinging the MUSB board with ping -s54.
+        */
+       if ((chdat->transfer_len < chdat->packet_sz)
+                       || (chdat->transfer_len % chdat->packet_sz != 0)) {
+               u16     csr;
+
+               if (chdat->tx) {
+                       DBG(3, "terminating short tx packet\n");
+                       musb_ep_select(mbase, chdat->epnum);
+                       csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
+                       csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY
+                               | MUSB_TXCSR_P_WZC_BITS;
+                       musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
+               }
+       }
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
+                               u8 rndis_mode, dma_addr_t dma_addr, u32 len)
+{
+       struct tusb_omap_dma_ch         *chdat = to_chdat(channel);
+       struct tusb_omap_dma            *tusb_dma = chdat->tusb_dma;
+       struct musb                     *musb = chdat->musb;
+       struct musb_hw_ep               *hw_ep = chdat->hw_ep;
+       void __iomem                    *mbase = musb->mregs;
+       void __iomem                    *ep_conf = hw_ep->conf;
+       dma_addr_t                      fifo = hw_ep->fifo_sync;
+       struct omap_dma_channel_params  dma_params;
+       u32                             dma_remaining;
+       int                             src_burst, dst_burst;
+       u16                             csr;
+       int                             ch;
+       s8                              dmareq;
+       s8                              sync_dev;
+
+       if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
+               return false;
+
+       /*
+        * HW issue #10: Async dma will eventually corrupt the XFR_SIZE
+        * register which will cause missed DMA interrupt. We could try to
+        * use a timer for the callback, but it is unsafe as the XFR_SIZE
+        * register is corrupt, and we won't know if the DMA worked.
+        */
+       if (dma_addr & 0x2)
+               return false;
+
+       /*
+        * Because of HW issue #10, it seems like mixing sync DMA and async
+        * PIO access can confuse the DMA. Make sure XFR_SIZE is reset before
+        * using the channel for DMA.
+        */
+       if (chdat->tx)
+               dma_remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
+       else
+               dma_remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET);
+
+       dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
+       if (dma_remaining) {
+               DBG(2, "Busy %s dma ch%i, not using: %08x\n",
+                       chdat->tx ? "tx" : "rx", chdat->ch,
+                       dma_remaining);
+               return false;
+       }
+
+       chdat->transfer_len = len & ~0x1f;
+
+       if (len < packet_sz)
+               chdat->transfer_packet_sz = chdat->transfer_len;
+       else
+               chdat->transfer_packet_sz = packet_sz;
+
+       if (tusb_dma->multichannel) {
+               ch = chdat->ch;
+               dmareq = chdat->dmareq;
+               sync_dev = chdat->sync_dev;
+       } else {
+               if (tusb_omap_use_shared_dmareq(chdat) != 0) {
+                       DBG(3, "could not get dma for ep%i\n", chdat->epnum);
+                       return false;
+               }
+               if (tusb_dma->ch < 0) {
+                       /* REVISIT: This should get blocked earlier, happens
+                        * with MSC ErrorRecoveryTest
+                        */
+                       WARN_ON(1);
+                       return false;
+               }
+
+               ch = tusb_dma->ch;
+               dmareq = tusb_dma->dmareq;
+               sync_dev = tusb_dma->sync_dev;
+               omap_set_dma_callback(ch, tusb_omap_dma_cb, channel);
+       }
+
+       chdat->packet_sz = packet_sz;
+       chdat->len = len;
+       channel->actual_len = 0;
+       chdat->dma_addr = (void __iomem *)dma_addr;
+       channel->status = MUSB_DMA_STATUS_BUSY;
+
+       /* Since we're recycling dma areas, we need to clean or invalidate */
+       if (chdat->tx)
+               dma_cache_maint(phys_to_virt(dma_addr), len, DMA_TO_DEVICE);
+       else
+               dma_cache_maint(phys_to_virt(dma_addr), len, DMA_FROM_DEVICE);
+
+       /* Use 16-bit transfer if dma_addr is not 32-bit aligned */
+       if ((dma_addr & 0x3) == 0) {
+               dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
+               dma_params.elem_count = 8;              /* Elements in frame */
+       } else {
+               dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
+               dma_params.elem_count = 16;             /* Elements in frame */
+               fifo = hw_ep->fifo_async;
+       }
+
+       dma_params.frame_count  = chdat->transfer_len / 32; /* Burst sz frame */
+
+       DBG(3, "ep%i %s dma ch%i dma: %08x len: %u(%u) packet_sz: %i(%i)\n",
+               chdat->epnum, chdat->tx ? "tx" : "rx",
+               ch, dma_addr, chdat->transfer_len, len,
+               chdat->transfer_packet_sz, packet_sz);
+
+       /*
+        * Prepare omap DMA for transfer
+        */
+       if (chdat->tx) {
+               dma_params.src_amode    = OMAP_DMA_AMODE_POST_INC;
+               dma_params.src_start    = (unsigned long)dma_addr;
+               dma_params.src_ei       = 0;
+               dma_params.src_fi       = 0;
+
+               dma_params.dst_amode    = OMAP_DMA_AMODE_DOUBLE_IDX;
+               dma_params.dst_start    = (unsigned long)fifo;
+               dma_params.dst_ei       = 1;
+               dma_params.dst_fi       = -31;  /* Loop 32 byte window */
+
+               dma_params.trigger      = sync_dev;
+               dma_params.sync_mode    = OMAP_DMA_SYNC_FRAME;
+               dma_params.src_or_dst_synch     = 0;    /* Dest sync */
+
+               src_burst = OMAP_DMA_DATA_BURST_16;     /* 16x32 read */
+               dst_burst = OMAP_DMA_DATA_BURST_8;      /* 8x32 write */
+       } else {
+               dma_params.src_amode    = OMAP_DMA_AMODE_DOUBLE_IDX;
+               dma_params.src_start    = (unsigned long)fifo;
+               dma_params.src_ei       = 1;
+               dma_params.src_fi       = -31;  /* Loop 32 byte window */
+
+               dma_params.dst_amode    = OMAP_DMA_AMODE_POST_INC;
+               dma_params.dst_start    = (unsigned long)dma_addr;
+               dma_params.dst_ei       = 0;
+               dma_params.dst_fi       = 0;
+
+               dma_params.trigger      = sync_dev;
+               dma_params.sync_mode    = OMAP_DMA_SYNC_FRAME;
+               dma_params.src_or_dst_synch     = 1;    /* Source sync */
+
+               src_burst = OMAP_DMA_DATA_BURST_8;      /* 8x32 read */
+               dst_burst = OMAP_DMA_DATA_BURST_16;     /* 16x32 write */
+       }
+
+       DBG(3, "ep%i %s using %i-bit %s dma from 0x%08lx to 0x%08lx\n",
+               chdat->epnum, chdat->tx ? "tx" : "rx",
+               (dma_params.data_type == OMAP_DMA_DATA_TYPE_S32) ? 32 : 16,
+               ((dma_addr & 0x3) == 0) ? "sync" : "async",
+               dma_params.src_start, dma_params.dst_start);
+
+       omap_set_dma_params(ch, &dma_params);
+       omap_set_dma_src_burst_mode(ch, src_burst);
+       omap_set_dma_dest_burst_mode(ch, dst_burst);
+       omap_set_dma_write_mode(ch, OMAP_DMA_WRITE_LAST_NON_POSTED);
+
+       /*
+        * Prepare MUSB for DMA transfer
+        */
+       if (chdat->tx) {
+               musb_ep_select(mbase, chdat->epnum);
+               csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
+               csr |= (MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB
+                       | MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
+               csr &= ~MUSB_TXCSR_P_UNDERRUN;
+               musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
+       } else {
+               musb_ep_select(mbase, chdat->epnum);
+               csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
+               csr |= MUSB_RXCSR_DMAENAB;
+               csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAMODE);
+               musb_writew(hw_ep->regs, MUSB_RXCSR,
+                       csr | MUSB_RXCSR_P_WZC_BITS);
+       }
+
+       /*
+        * Start DMA transfer
+        */
+       omap_start_dma(ch);
+
+       if (chdat->tx) {
+               /* Send transfer_packet_sz packets at a time */
+               musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
+                       chdat->transfer_packet_sz);
+
+               musb_writel(ep_conf, TUSB_EP_TX_OFFSET,
+                       TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
+       } else {
+               /* Receive transfer_packet_sz packets at a time */
+               musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
+                       chdat->transfer_packet_sz << 16);
+
+               musb_writel(ep_conf, TUSB_EP_RX_OFFSET,
+                       TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
+       }
+
+       return true;
+}
+
+static int tusb_omap_dma_abort(struct dma_channel *channel)
+{
+       struct tusb_omap_dma_ch *chdat = to_chdat(channel);
+       struct tusb_omap_dma    *tusb_dma = chdat->tusb_dma;
+
+       if (!tusb_dma->multichannel) {
+               if (tusb_dma->ch >= 0) {
+                       omap_stop_dma(tusb_dma->ch);
+                       omap_free_dma(tusb_dma->ch);
+                       tusb_dma->ch = -1;
+               }
+
+               tusb_dma->dmareq = -1;
+               tusb_dma->sync_dev = -1;
+       }
+
+       channel->status = MUSB_DMA_STATUS_FREE;
+
+       return 0;
+}
+
+static inline int tusb_omap_dma_allocate_dmareq(struct tusb_omap_dma_ch *chdat)
+{
+       u32             reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
+       int             i, dmareq_nr = -1;
+
+       const int sync_dev[6] = {
+               OMAP24XX_DMA_EXT_DMAREQ0,
+               OMAP24XX_DMA_EXT_DMAREQ1,
+               OMAP242X_DMA_EXT_DMAREQ2,
+               OMAP242X_DMA_EXT_DMAREQ3,
+               OMAP242X_DMA_EXT_DMAREQ4,
+               OMAP242X_DMA_EXT_DMAREQ5,
+       };
+
+       for (i = 0; i < MAX_DMAREQ; i++) {
+               int cur = (reg & (0xf << (i * 5))) >> (i * 5);
+               if (cur == 0) {
+                       dmareq_nr = i;
+                       break;
+               }
+       }
+
+       if (dmareq_nr == -1)
+               return -EAGAIN;
+
+       reg |= (chdat->epnum << (dmareq_nr * 5));
+       if (chdat->tx)
+               reg |= ((1 << 4) << (dmareq_nr * 5));
+       musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
+
+       chdat->dmareq = dmareq_nr;
+       chdat->sync_dev = sync_dev[chdat->dmareq];
+
+       return 0;
+}
+
+static inline void tusb_omap_dma_free_dmareq(struct tusb_omap_dma_ch *chdat)
+{
+       u32 reg;
+
+       if (!chdat || chdat->dmareq < 0)
+               return;
+
+       reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
+       reg &= ~(0x1f << (chdat->dmareq * 5));
+       musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
+
+       chdat->dmareq = -1;
+       chdat->sync_dev = -1;
+}
+
+static struct dma_channel *dma_channel_pool[MAX_DMAREQ];
+
+static struct dma_channel *
+tusb_omap_dma_allocate(struct dma_controller *c,
+               struct musb_hw_ep *hw_ep,
+               u8 tx)
+{
+       int ret, i;
+       const char              *dev_name;
+       struct tusb_omap_dma    *tusb_dma;
+       struct musb             *musb;
+       void __iomem            *tbase;
+       struct dma_channel      *channel = NULL;
+       struct tusb_omap_dma_ch *chdat = NULL;
+       u32                     reg;
+
+       tusb_dma = container_of(c, struct tusb_omap_dma, controller);
+       musb = tusb_dma->musb;
+       tbase = musb->ctrl_base;
+
+       reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
+       if (tx)
+               reg &= ~(1 << hw_ep->epnum);
+       else
+               reg &= ~(1 << (hw_ep->epnum + 15));
+       musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
+
+       /* REVISIT: Why does dmareq5 not work? */
+       if (hw_ep->epnum == 0) {
+               DBG(3, "Not allowing DMA for ep0 %s\n", tx ? "tx" : "rx");
+               return NULL;
+       }
+
+       for (i = 0; i < MAX_DMAREQ; i++) {
+               struct dma_channel *ch = dma_channel_pool[i];
+               if (ch->status == MUSB_DMA_STATUS_UNKNOWN) {
+                       ch->status = MUSB_DMA_STATUS_FREE;
+                       channel = ch;
+                       chdat = ch->private_data;
+                       break;
+               }
+       }
+
+       if (!channel)
+               return NULL;
+
+       if (tx) {
+               chdat->tx = 1;
+               dev_name = "TUSB transmit";
+       } else {
+               chdat->tx = 0;
+               dev_name = "TUSB receive";
+       }
+
+       chdat->musb = tusb_dma->musb;
+       chdat->tbase = tusb_dma->tbase;
+       chdat->hw_ep = hw_ep;
+       chdat->epnum = hw_ep->epnum;
+       chdat->dmareq = -1;
+       chdat->completed_len = 0;
+       chdat->tusb_dma = tusb_dma;
+
+       channel->max_len = 0x7fffffff;
+       channel->desired_mode = 0;
+       channel->actual_len = 0;
+
+       if (tusb_dma->multichannel) {
+               ret = tusb_omap_dma_allocate_dmareq(chdat);
+               if (ret != 0)
+                       goto free_dmareq;
+
+               ret = omap_request_dma(chdat->sync_dev, dev_name,
+                               tusb_omap_dma_cb, channel, &chdat->ch);
+               if (ret != 0)
+                       goto free_dmareq;
+       } else if (tusb_dma->ch == -1) {
+               tusb_dma->dmareq = 0;
+               tusb_dma->sync_dev = OMAP24XX_DMA_EXT_DMAREQ0;
+
+               /* Callback data gets set later in the shared dmareq case */
+               ret = omap_request_dma(tusb_dma->sync_dev, "TUSB shared",
+                               tusb_omap_dma_cb, NULL, &tusb_dma->ch);
+               if (ret != 0)
+                       goto free_dmareq;
+
+               chdat->dmareq = -1;
+               chdat->ch = -1;
+       }
+
+       DBG(3, "ep%i %s dma: %s dma%i dmareq%i sync%i\n",
+               chdat->epnum,
+               chdat->tx ? "tx" : "rx",
+               chdat->ch >= 0 ? "dedicated" : "shared",
+               chdat->ch >= 0 ? chdat->ch : tusb_dma->ch,
+               chdat->dmareq >= 0 ? chdat->dmareq : tusb_dma->dmareq,
+               chdat->sync_dev >= 0 ? chdat->sync_dev : tusb_dma->sync_dev);
+
+       return channel;
+
+free_dmareq:
+       tusb_omap_dma_free_dmareq(chdat);
+
+       DBG(3, "ep%i: Could not get a DMA channel\n", chdat->epnum);
+       channel->status = MUSB_DMA_STATUS_UNKNOWN;
+
+       return NULL;
+}
+
+static void tusb_omap_dma_release(struct dma_channel *channel)
+{
+       struct tusb_omap_dma_ch *chdat = to_chdat(channel);
+       struct musb             *musb = chdat->musb;
+       void __iomem            *tbase = musb->ctrl_base;
+       u32                     reg;
+
+       DBG(3, "ep%i ch%i\n", chdat->epnum, chdat->ch);
+
+       reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
+       if (chdat->tx)
+               reg |= (1 << chdat->epnum);
+       else
+               reg |= (1 << (chdat->epnum + 15));
+       musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
+
+       reg = musb_readl(tbase, TUSB_DMA_INT_CLEAR);
+       if (chdat->tx)
+               reg |= (1 << chdat->epnum);
+       else
+               reg |= (1 << (chdat->epnum + 15));
+       musb_writel(tbase, TUSB_DMA_INT_CLEAR, reg);
+
+       channel->status = MUSB_DMA_STATUS_UNKNOWN;
+
+       if (chdat->ch >= 0) {
+               omap_stop_dma(chdat->ch);
+               omap_free_dma(chdat->ch);
+               chdat->ch = -1;
+       }
+
+       if (chdat->dmareq >= 0)
+               tusb_omap_dma_free_dmareq(chdat);
+
+       channel = NULL;
+}
+
+void dma_controller_destroy(struct dma_controller *c)
+{
+       struct tusb_omap_dma    *tusb_dma;
+       int                     i;
+
+       tusb_dma = container_of(c, struct tusb_omap_dma, controller);
+       for (i = 0; i < MAX_DMAREQ; i++) {
+               struct dma_channel *ch = dma_channel_pool[i];
+               if (ch) {
+                       kfree(ch->private_data);
+                       kfree(ch);
+               }
+       }
+
+       if (!tusb_dma->multichannel && tusb_dma && tusb_dma->ch >= 0)
+               omap_free_dma(tusb_dma->ch);
+
+       kfree(tusb_dma);
+}
+
+struct dma_controller *__init
+dma_controller_create(struct musb *musb, void __iomem *base)
+{
+       void __iomem            *tbase = musb->ctrl_base;
+       struct tusb_omap_dma    *tusb_dma;
+       int                     i;
+
+       /* REVISIT: Get dmareq lines used from board-*.c */
+
+       musb_writel(musb->ctrl_base, TUSB_DMA_INT_MASK, 0x7fffffff);
+       musb_writel(musb->ctrl_base, TUSB_DMA_EP_MAP, 0);
+
+       musb_writel(tbase, TUSB_DMA_REQ_CONF,
+               TUSB_DMA_REQ_CONF_BURST_SIZE(2)
+               | TUSB_DMA_REQ_CONF_DMA_REQ_EN(0x3f)
+               | TUSB_DMA_REQ_CONF_DMA_REQ_ASSER(2));
+
+       tusb_dma = kzalloc(sizeof(struct tusb_omap_dma), GFP_KERNEL);
+       if (!tusb_dma)
+               goto cleanup;
+
+       tusb_dma->musb = musb;
+       tusb_dma->tbase = musb->ctrl_base;
+
+       tusb_dma->ch = -1;
+       tusb_dma->dmareq = -1;
+       tusb_dma->sync_dev = -1;
+
+       tusb_dma->controller.start = tusb_omap_dma_start;
+       tusb_dma->controller.stop = tusb_omap_dma_stop;
+       tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate;
+       tusb_dma->controller.channel_release = tusb_omap_dma_release;
+       tusb_dma->controller.channel_program = tusb_omap_dma_program;
+       tusb_dma->controller.channel_abort = tusb_omap_dma_abort;
+
+       if (tusb_get_revision(musb) >= TUSB_REV_30)
+               tusb_dma->multichannel = 1;
+
+       for (i = 0; i < MAX_DMAREQ; i++) {
+               struct dma_channel      *ch;
+               struct tusb_omap_dma_ch *chdat;
+
+               ch = kzalloc(sizeof(struct dma_channel), GFP_KERNEL);
+               if (!ch)
+                       goto cleanup;
+
+               dma_channel_pool[i] = ch;
+
+               chdat = kzalloc(sizeof(struct tusb_omap_dma_ch), GFP_KERNEL);
+               if (!chdat)
+                       goto cleanup;
+
+               ch->status = MUSB_DMA_STATUS_UNKNOWN;
+               ch->private_data = chdat;
+       }
+
+       return &tusb_dma->controller;
+
+cleanup:
+       dma_controller_destroy(&tusb_dma->controller);
+
+       return NULL;
+}
index 8878c1767fc88aedbcbb1e3035c0c7edf30af304..70338f4ec9188357f6a5d25716fe666ead6765b1 100644 (file)
@@ -499,9 +499,10 @@ config USB_SERIAL_SAFE_PADDED
 config USB_SERIAL_SIERRAWIRELESS
        tristate "USB Sierra Wireless Driver"
        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
-         instead).
+         Say M here if you want to use Sierra Wireless devices.
+
+         Many deviecs have a feature known as TRU-Install, for those devices
+         to work properly the USB Storage Sierra feature must be enabled.
 
          To compile this driver as a module, choose M here: the
          module will be called sierra.
index 83871725014575d391acf77f6d27bf6aadc27c53..984f6eff4c475acb6cdfdb85407897aac9e87d01 100644 (file)
@@ -563,6 +563,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1010PC_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_ELV_HS485_PID) },
        { USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
        { USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
        { USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
@@ -637,6 +638,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) },
        { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
        { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
@@ -646,6 +648,10 @@ static struct usb_device_id id_table_combined [] = {
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(FTDI_VID, LMI_LM3S_DEVEL_BOARD_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
        { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
        { },                                    /* Optional parameter entry */
index a577ea44dcf9dceb13d2d5644feb73015451a428..382265bba9690b84eaf51c57b16a0e460c3f29ee 100644 (file)
 #define FTDI_ELV_WS300PC_PID   0xE0F6  /* PC-Wetterstation (WS 300 PC) */
 #define FTDI_ELV_FHZ1300PC_PID 0xE0E8  /* FHZ 1300 PC */
 #define FTDI_ELV_WS500_PID     0xE0E9  /* PC-Wetterstation (WS 500) */
+#define FTDI_ELV_HS485_PID     0xE0EA  /* USB to RS-485 adapter */
 #define FTDI_ELV_EM1010PC_PID  0xE0EF  /* Engery monitor EM 1010 PC */
+#define FTDI_PHI_FISCO_PID      0xE40B  /* PHI Fisco USB to Serial cable */
 
 /*
  * Definitions for ID TECH (www.idt-net.com) devices
 #define OLIMEX_VID                     0x15BA
 #define OLIMEX_ARM_USB_OCD_PID         0x0003
 
+/* Luminary Micro Stellaris Boards, VID = FTDI_VID */
+/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */
+#define LMI_LM3S_DEVEL_BOARD_PID       0xbcd8
+#define LMI_LM3S_EVAL_BOARD_PID                0xbcd9
+
 /* www.elsterelectricity.com Elster Unicom III Optical Probe */
 #define FTDI_ELSTER_UNICOM_PID         0xE700 /* Product Id */
 
index e4eca95f2b0f7aa984cc8194ad0f4c755a908116..e143198aeb028e0bec63189cf8d4ace46e778a70 100644 (file)
@@ -186,6 +186,23 @@ static int  option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
 #define BANDRICH_VENDOR_ID                     0x1A8D
 #define BANDRICH_PRODUCT_C100_1                        0x1002
 #define BANDRICH_PRODUCT_C100_2                        0x1003
+#define BANDRICH_PRODUCT_1004                  0x1004
+#define BANDRICH_PRODUCT_1005                  0x1005
+#define BANDRICH_PRODUCT_1006                  0x1006
+#define BANDRICH_PRODUCT_1007                  0x1007
+#define BANDRICH_PRODUCT_1008                  0x1008
+#define BANDRICH_PRODUCT_1009                  0x1009
+#define BANDRICH_PRODUCT_100A                  0x100a
+
+#define BANDRICH_PRODUCT_100B                  0x100b
+#define BANDRICH_PRODUCT_100C                  0x100c
+#define BANDRICH_PRODUCT_100D                  0x100d
+#define BANDRICH_PRODUCT_100E                  0x100e
+
+#define BANDRICH_PRODUCT_100F                  0x100f
+#define BANDRICH_PRODUCT_1010                  0x1010
+#define BANDRICH_PRODUCT_1011                  0x1011
+#define BANDRICH_PRODUCT_1012                  0x1012
 
 #define AMOI_VENDOR_ID                 0x1614
 #define AMOI_PRODUCT_9508                      0x0800
@@ -197,6 +214,10 @@ static int  option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
 #define TELIT_VENDOR_ID                                0x1bc7
 #define TELIT_PRODUCT_UC864E                   0x1003
 
+/* ZTE PRODUCTS */
+#define ZTE_VENDOR_ID                          0x19d2
+#define ZTE_PRODUCT_MF628                      0x0015
+
 static struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -302,12 +323,28 @@ static struct usb_device_id option_ids[] = {
        { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
        { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
        { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011) },
+       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
        { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
+       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
@@ -346,11 +383,7 @@ static struct usb_serial_driver option_1port_device = {
        .read_int_callback = option_instat_callback,
 };
 
-#ifdef CONFIG_USB_DEBUG
 static int debug;
-#else
-#define debug 0
-#endif
 
 /* per port private data */
 
@@ -954,8 +987,5 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
-#ifdef CONFIG_USB_DEBUG
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug messages");
-#endif
-
index 2c9c446ad625ded55144ad36955abc6bef07ddfa..1ede1441cb1b8aca43e699d3dbc0d1d45d9b5431 100644 (file)
@@ -90,7 +90,6 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
        { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
        { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
-       { USB_DEVICE(HL340_VENDOR_ID, HL340_PRODUCT_ID) },
        { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
        { }                                     /* Terminating entry */
 };
index 6ac3bbcf7a22903b392d2281e2627f5db92e93fc..a3bd039c78e96769beeff504e4da6c32f63daa14 100644 (file)
 #define COREGA_VENDOR_ID       0x07aa
 #define COREGA_PRODUCT_ID      0x002a
 
-/* HL HL-340 (ID: 4348:5523) */
-#define HL340_VENDOR_ID                0x4348
-#define HL340_PRODUCT_ID       0x5523
-
 /* Y.C. Cable U.S.A., Inc - USB to RS-232 */
 #define YCCABLE_VENDOR_ID      0x05ad
 #define YCCABLE_PRODUCT_ID     0x0fba
index 2f6f1523ec56b5462461fbf1a6c1e260513919d9..706033753adb7836db59e343310022e2469436e5 100644 (file)
@@ -14,7 +14,7 @@
   Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
 */
 
-#define DRIVER_VERSION "v.1.2.9c"
+#define DRIVER_VERSION "v.1.2.13a"
 #define DRIVER_AUTHOR "Kevin Lloyd <klloyd@sierrawireless.com>"
 #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
 
@@ -31,6 +31,7 @@
 #define SWIMS_USB_REQUEST_SetPower     0x00
 #define SWIMS_USB_REQUEST_SetNmea      0x07
 #define SWIMS_USB_REQUEST_SetMode      0x0B
+#define SWIMS_USB_REQUEST_GetSwocInfo  0x0A
 #define SWIMS_SET_MODE_Modem           0x0001
 
 /* per port private data */
 
 static int debug;
 static int nmea;
-static int truinstall = 1;
-
-enum devicetype {
-       DEVICE_3_PORT =         0,
-       DEVICE_1_PORT =         1,
-       DEVICE_INSTALLER =      2,
-};
 
 static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
 {
        int result;
-       dev_dbg(&udev->dev, "%s", "SET POWER STATE\n");
+       dev_dbg(&udev->dev, "%s", __func__);
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                        SWIMS_USB_REQUEST_SetPower,     /* __u8 request      */
                        USB_TYPE_VENDOR,                /* __u8 request type */
@@ -63,25 +57,10 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
        return result;
 }
 
-static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
-{
-       int result;
-       dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH\n");
-       result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                       SWIMS_USB_REQUEST_SetMode,      /* __u8 request      */
-                       USB_TYPE_VENDOR,                /* __u8 request type */
-                       eSWocMode,                      /* __u16 value       */
-                       0x0000,                         /* __u16 index       */
-                       NULL,                           /* void *data        */
-                       0,                              /* __u16 size        */
-                       USB_CTRL_SET_TIMEOUT);          /* int timeout       */
-       return result;
-}
-
 static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
 {
        int result;
-       dev_dbg(&udev->dev, "%s", "NMEA Enable sent\n");
+       dev_dbg(&udev->dev, "%s", __func__);
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                        SWIMS_USB_REQUEST_SetNmea,      /* __u8 request      */
                        USB_TYPE_VENDOR,                /* __u8 request type */
@@ -97,6 +76,7 @@ static int sierra_calc_num_ports(struct usb_serial *serial)
 {
        int result;
        int *num_ports = usb_get_serial_data(serial);
+       dev_dbg(&serial->dev->dev, "%s", __func__);
 
        result = *num_ports;
 
@@ -110,22 +90,23 @@ static int sierra_calc_num_ports(struct usb_serial *serial)
 
 static int sierra_calc_interface(struct usb_serial *serial)
 {
-               int interface;
-               struct usb_interface *p_interface;
-               struct usb_host_interface *p_host_interface;
+       int interface;
+       struct usb_interface *p_interface;
+       struct usb_host_interface *p_host_interface;
+       dev_dbg(&serial->dev->dev, "%s", __func__);
 
-               /* Get the interface structure pointer from the serial struct */
-               p_interface = serial->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;
+       /* 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;
+       /* 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;
+       return interface;
 }
 
 static int sierra_probe(struct usb_serial *serial,
@@ -135,43 +116,40 @@ static int sierra_probe(struct usb_serial *serial,
        struct usb_device *udev;
        int *num_ports;
        u8 ifnum;
+       u8 numendpoints;
+
+       dev_dbg(&serial->dev->dev, "%s", __func__);
 
        num_ports = kmalloc(sizeof(*num_ports), GFP_KERNEL);
        if (!num_ports)
                return -ENOMEM;
 
        ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+       numendpoints = serial->interface->cur_altsetting->desc.bNumEndpoints;
        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);
+       /* Figure out the interface number from the serial structure */
+       ifnum = sierra_calc_interface(serial);
 
-                       /* We know the alternate setting is 1 for the MC8785 */
-                       usb_set_interface(udev, ifnum, 1);
-               }
+       /*
+        * 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");
-               result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);
-               /* Don't bind to the device when in installer mode */
-               kfree(num_ports);
-               return -EIO;
-       } else if (id->driver_info == DEVICE_1_PORT)
-               *num_ports = 1;
-       else if (ifnum == 0x99)
+       /* Dummy interface present on some SKUs should be ignored */
+       if (ifnum == 0x99)
                *num_ports = 0;
+       else if (numendpoints <= 3)
+               *num_ports = 1;
        else
-               *num_ports = 3;
+               *num_ports = (numendpoints-1)/2;
+
        /*
         * save off our num_ports info so that we can use it in the
         * calc_num_ports callback
@@ -187,40 +165,50 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
        { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */
        { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
+       { USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */
        { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */
        { 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_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) }, /* Sierra Wireless C597 */
+        /* Sierra Wireless C597 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) },
+        /* Sierra Wireless Device */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) },
+       { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless Device */
 
        { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
        { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
        { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
        { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */
-       { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Thinkpad internal) */
+       { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Lenovo) */
        { 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, 0x6832) }, /* Sierra Wireless MC8780 */
+       { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */
+       { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */
+       { USB_DEVICE(0x1199, 0x683C) }, /* Sierra Wireless MC8790 */
+       { USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8790 */
+       { USB_DEVICE(0x1199, 0x683E) }, /* Sierra Wireless MC8790 */
        { 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 */
-
-       { USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */
-       { USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */
+       { USB_DEVICE(0x1199, 0x6859) }, /* Sierra Wireless AirCard 885 E */
+       { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */
+       /* Sierra Wireless C885 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)},
+       /* Sierra Wireless Device */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)},
+       /* Sierra Wireless Device */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
+
+       { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
+       { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
 
-       { USB_DEVICE(0x1199, 0x0FFF), .driver_info = DEVICE_INSTALLER},
        { }
 };
 MODULE_DEVICE_TABLE(usb, id_table);
@@ -268,13 +256,19 @@ static int sierra_send_setup(struct tty_struct *tty,
                if (portdata->rts_state)
                        val |= 0x02;
 
-               /* Determine which port is targeted */
-               if (port->bulk_out_endpointAddress == 2)
-                       interface = 0;
-               else if (port->bulk_out_endpointAddress == 4)
-                       interface = 1;
-               else if (port->bulk_out_endpointAddress == 5)
-                       interface = 2;
+               /* If composite device then properly report interface */
+               if (serial->num_ports == 1)
+                       interface = sierra_calc_interface(serial);
+
+               /* Otherwise the need to do non-composite mapping */
+               else {
+                       if (port->bulk_out_endpointAddress == 2)
+                               interface = 0;
+                       else if (port->bulk_out_endpointAddress == 4)
+                               interface = 1;
+                       else if (port->bulk_out_endpointAddress == 5)
+                               interface = 2;
+               }
 
                return usb_control_msg(serial->dev,
                                usb_rcvctrlpipe(serial->dev, 0),
@@ -713,7 +707,7 @@ static void sierra_shutdown(struct usb_serial *serial)
 static struct usb_serial_driver sierra_device = {
        .driver = {
                .owner =        THIS_MODULE,
-               .name =         "sierra1",
+               .name =         "sierra",
        },
        .description       = "Sierra USB modem",
        .id_table          = id_table,
@@ -769,14 +763,8 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
-module_param(truinstall, bool, 0);
-MODULE_PARM_DESC(truinstall, "TRU-Install support");
-
-module_param(nmea, bool, 0);
+module_param(nmea, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(nmea, "NMEA streaming");
 
-#ifdef CONFIG_USB_DEBUG
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug messages");
-#endif
-
index 8c2d531eedea1f3bf2759ec9796dcf96cb8dcfff..b157c48e8b78df594bd0386f5ff38a725cf18929 100644 (file)
@@ -122,9 +122,6 @@ static void return_serial(struct usb_serial *serial)
 
        dbg("%s", __func__);
 
-       if (serial == NULL)
-               return;
-
        for (i = 0; i < serial->num_ports; ++i)
                serial_table[serial->minor + i] = NULL;
 }
@@ -142,7 +139,8 @@ static void destroy_serial(struct kref *kref)
        serial->type->shutdown(serial);
 
        /* return the minor range that this device had */
-       return_serial(serial);
+       if (serial->minor != SERIAL_TTY_NO_MINOR)
+               return_serial(serial);
 
        for (i = 0; i < serial->num_ports; ++i)
                serial->port[i]->port.count = 0;
@@ -575,6 +573,7 @@ static struct usb_serial *create_serial(struct usb_device *dev,
        serial->interface = interface;
        kref_init(&serial->kref);
        mutex_init(&serial->disc_mutex);
+       serial->minor = SERIAL_TTY_NO_MINOR;
 
        return serial;
 }
index 3d9249632ae12e7051174817241ef37ea6f2cd4c..c76034672c18c6c87220fc37e5913f45e95be782 100644 (file)
@@ -146,6 +146,18 @@ config USB_STORAGE_KARMA
          on the resulting scsi device node returns the Karma to normal
          operation.
 
+config USB_STORAGE_SIERRA
+       bool "Sierra Wireless TRU-Install Feature Support"
+       depends on USB_STORAGE
+       help
+         Say Y here to include additional code to support Sierra Wireless
+         products with the TRU-Install feature (e.g., AC597E, AC881U).
+
+         This code switches the Sierra Wireless device from being in
+         Mass Storage mode to Modem mode. It also has the ability to
+         support host software upgrades should full Linux support be added
+         to TRU-Install.
+
 config USB_STORAGE_CYPRESS_ATACB
        bool "SAT emulation on Cypress USB/ATA Bridge with ATACB"
        depends on USB_STORAGE
index 4c596c766c53c61c2ee460d3a6e54a042e86e171..bc3415b475c9b5675d0aec6d33cf0f117d7862da 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_SIERRA)   += sierra_ms.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o
 
 usb-storage-objs :=    scsiglue.o protocol.o transport.o usb.o \
diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c
new file mode 100644 (file)
index 0000000..4359a2c
--- /dev/null
@@ -0,0 +1,207 @@
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <linux/usb.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "protocol.h"
+#include "scsiglue.h"
+#include "sierra_ms.h"
+#include "debug.h"
+
+#define SWIMS_USB_REQUEST_SetSwocMode  0x0B
+#define SWIMS_USB_REQUEST_GetSwocInfo  0x0A
+#define SWIMS_USB_INDEX_SetMode                0x0000
+#define SWIMS_SET_MODE_Modem           0x0001
+
+#define TRU_NORMAL                     0x01
+#define TRU_FORCE_MS                   0x02
+#define TRU_FORCE_MODEM                0x03
+
+static unsigned int swi_tru_install = 1;
+module_param(swi_tru_install, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(swi_tru_install, "TRU-Install mode (1=Full Logic (def),"
+                " 2=Force CD-Rom, 3=Force Modem)");
+
+struct swoc_info {
+       __u8 rev;
+       __u8 reserved[8];
+       __u16 LinuxSKU;
+       __u16 LinuxVer;
+       __u8 reserved2[47];
+} __attribute__((__packed__));
+
+static bool containsFullLinuxPackage(struct swoc_info *swocInfo)
+{
+       if ((swocInfo->LinuxSKU >= 0x2100 && swocInfo->LinuxSKU <= 0x2FFF) ||
+          (swocInfo->LinuxSKU >= 0x7100 && swocInfo->LinuxSKU <= 0x7FFF))
+               return true;
+       else
+               return false;
+}
+
+static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
+{
+       int result;
+       US_DEBUGP("SWIMS: %s", "DEVICE MODE SWITCH\n");
+       result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                       SWIMS_USB_REQUEST_SetSwocMode,  /* __u8 request      */
+                       USB_TYPE_VENDOR | USB_DIR_OUT,  /* __u8 request type */
+                       eSWocMode,                      /* __u16 value       */
+                       0x0000,                         /* __u16 index       */
+                       NULL,                           /* void *data        */
+                       0,                              /* __u16 size        */
+                       USB_CTRL_SET_TIMEOUT);          /* int timeout       */
+       return result;
+}
+
+
+static int sierra_get_swoc_info(struct usb_device *udev,
+                               struct swoc_info *swocInfo)
+{
+       int result;
+
+       US_DEBUGP("SWIMS: Attempting to get TRU-Install info.\n");
+
+       result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                       SWIMS_USB_REQUEST_GetSwocInfo,  /* __u8 request      */
+                       USB_TYPE_VENDOR | USB_DIR_IN,   /* __u8 request type */
+                       0,                              /* __u16 value       */
+                       0,                              /* __u16 index       */
+                       (void *) swocInfo,              /* void *data        */
+                       sizeof(struct swoc_info),       /* __u16 size        */
+                       USB_CTRL_SET_TIMEOUT);          /* int timeout       */
+
+       swocInfo->LinuxSKU = le16_to_cpu(swocInfo->LinuxSKU);
+       swocInfo->LinuxVer = le16_to_cpu(swocInfo->LinuxVer);
+       return result;
+}
+
+static void debug_swoc(struct swoc_info *swocInfo)
+{
+       US_DEBUGP("SWIMS: SWoC Rev: %02d \n", swocInfo->rev);
+       US_DEBUGP("SWIMS: Linux SKU: %04X \n", swocInfo->LinuxSKU);
+       US_DEBUGP("SWIMS: Linux Version: %04X \n", swocInfo->LinuxVer);
+}
+
+
+static ssize_t show_truinst(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct swoc_info *swocInfo;
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct usb_device *udev = interface_to_usbdev(intf);
+       int result;
+       if (swi_tru_install == TRU_FORCE_MS) {
+               result = snprintf(buf, PAGE_SIZE, "Forced Mass Storage\n");
+       } else {
+               swocInfo = kmalloc(sizeof(struct swoc_info), GFP_KERNEL);
+               if (!swocInfo) {
+                       US_DEBUGP("SWIMS: Allocation failure\n");
+                       snprintf(buf, PAGE_SIZE, "Error\n");
+                       return -ENOMEM;
+               }
+               result = sierra_get_swoc_info(udev, swocInfo);
+               if (result < 0) {
+                       US_DEBUGP("SWIMS: failed SWoC query\n");
+                       kfree(swocInfo);
+                       snprintf(buf, PAGE_SIZE, "Error\n");
+                       return -EIO;
+               }
+               debug_swoc(swocInfo);
+               result = snprintf(buf, PAGE_SIZE,
+                       "REV=%02d SKU=%04X VER=%04X\n",
+                       swocInfo->rev,
+                       swocInfo->LinuxSKU,
+                       swocInfo->LinuxVer);
+               kfree(swocInfo);
+       }
+       return result;
+}
+static DEVICE_ATTR(truinst, S_IWUGO | S_IRUGO, show_truinst, NULL);
+
+int sierra_ms_init(struct us_data *us)
+{
+       int result, retries;
+       signed long delay_t;
+       struct swoc_info *swocInfo;
+       struct usb_device *udev;
+       struct Scsi_Host *sh;
+       struct scsi_device *sd;
+
+       delay_t = 2;
+       retries = 3;
+       result = 0;
+       udev = us->pusb_dev;
+
+       sh = us_to_host(us);
+       sd = scsi_get_host_dev(sh);
+
+       US_DEBUGP("SWIMS: sierra_ms_init called\n");
+
+       /* Force Modem mode */
+       if (swi_tru_install == TRU_FORCE_MODEM) {
+               US_DEBUGP("SWIMS: %s", "Forcing Modem Mode\n");
+               result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);
+               if (result < 0)
+                       US_DEBUGP("SWIMS: Failed to switch to modem mode.\n");
+               return -EIO;
+       }
+       /* Force Mass Storage mode (keep CD-Rom) */
+       else if (swi_tru_install == TRU_FORCE_MS) {
+               US_DEBUGP("SWIMS: %s", "Forcing Mass Storage Mode\n");
+               goto complete;
+       }
+       /* Normal TRU-Install Logic */
+       else {
+               US_DEBUGP("SWIMS: %s", "Normal SWoC Logic\n");
+
+               swocInfo = kmalloc(sizeof(struct swoc_info),
+                               GFP_KERNEL);
+               if (!swocInfo) {
+                       US_DEBUGP("SWIMS: %s", "Allocation failure\n");
+                       return -ENOMEM;
+               }
+
+               retries = 3;
+               do {
+                       retries--;
+                       result = sierra_get_swoc_info(udev, swocInfo);
+                       if (result < 0) {
+                               US_DEBUGP("SWIMS: %s", "Failed SWoC query\n");
+                               schedule_timeout_uninterruptible(2*HZ);
+                       }
+               } while (retries && result < 0);
+
+               if (result < 0) {
+                       US_DEBUGP("SWIMS: %s",
+                                 "Completely failed SWoC query\n");
+                       kfree(swocInfo);
+                       return -EIO;
+               }
+
+               debug_swoc(swocInfo);
+
+               /* If there is not Linux software on the TRU-Install device
+                * then switch to modem mode
+                */
+               if (!containsFullLinuxPackage(swocInfo)) {
+                       US_DEBUGP("SWIMS: %s",
+                               "Switching to Modem Mode\n");
+                       result = sierra_set_ms_mode(udev,
+                               SWIMS_SET_MODE_Modem);
+                       if (result < 0)
+                               US_DEBUGP("SWIMS: Failed to switch modem\n");
+                       kfree(swocInfo);
+                       return -EIO;
+               }
+               kfree(swocInfo);
+       }
+complete:
+       result = device_create_file(&us->pusb_intf->dev, &dev_attr_truinst);
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
diff --git a/drivers/usb/storage/sierra_ms.h b/drivers/usb/storage/sierra_ms.h
new file mode 100644 (file)
index 0000000..bb48634
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _SIERRA_MS_H_
+#define _SIERRA_MS_H_
+extern int sierra_ms_init(struct us_data *us);
+#endif
index fcbbfdb7b2b0298edc3625ff6987b99be36a1b58..3523a0bfa0ffd429caf8414ff4adae858a4c2ef6 100644 (file)
@@ -1032,8 +1032,21 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
 
        /* try to compute the actual residue, based on how much data
         * was really transferred and what the device tells us */
-       if (residue) {
-               if (!(us->fflags & US_FL_IGNORE_RESIDUE)) {
+       if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) {
+
+               /* Heuristically detect devices that generate bogus residues
+                * by seeing what happens with INQUIRY and READ CAPACITY
+                * commands.
+                */
+               if (bcs->Status == US_BULK_STAT_OK &&
+                               scsi_get_resid(srb) == 0 &&
+                                       ((srb->cmnd[0] == INQUIRY &&
+                                               transfer_length == 36) ||
+                                       (srb->cmnd[0] == READ_CAPACITY &&
+                                               transfer_length == 8))) {
+                       us->fflags |= US_FL_IGNORE_RESIDUE;
+
+               } else {
                        residue = min(residue, transfer_length);
                        scsi_set_resid(srb, max(scsi_get_resid(srb),
                                                               (int) residue));
index 7ae69f55aa966a72fd68d7cda7330d11f2e3a9e1..ba412e68d474a70e13bf7b68543eeb5f32c3fad7 100644 (file)
@@ -225,6 +225,13 @@ UNUSUAL_DEV(  0x0421, 0x0495, 0x0370, 0x0370,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_MAX_SECTORS_64 ),
 
+/* Reported by Cedric Godin <cedric@belbone.be> */
+UNUSUAL_DEV(  0x0421, 0x04b9, 0x0551, 0x0551,
+               "Nokia",
+               "5300",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_CAPACITY ),
+
 /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
 UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
                "SMSC",
@@ -356,14 +363,14 @@ UNUSUAL_DEV(  0x04b0, 0x040f, 0x0100, 0x0200,
                US_FL_FIX_CAPACITY),
 
 /* Reported by Emil Larsson <emil@swip.net> */
-UNUSUAL_DEV(  0x04b0, 0x0411, 0x0100, 0x0110,
+UNUSUAL_DEV(  0x04b0, 0x0411, 0x0100, 0x0111,
                "NIKON",
                "NIKON DSC D80",
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY),
 
 /* Reported by Ortwin Glueck <odi@odi.ch> */
-UNUSUAL_DEV(  0x04b0, 0x0413, 0x0110, 0x0110,
+UNUSUAL_DEV(  0x04b0, 0x0413, 0x0110, 0x0111,
                "NIKON",
                "NIKON DSC D40",
                US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -1185,6 +1192,13 @@ UNUSUAL_DEV(  0x07c4, 0xa400, 0x0000, 0xffff,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_FIX_INQUIRY ),
 
+/* Reported by Rauch Wolke <rauchwolke@gmx.net> */
+UNUSUAL_DEV(  0x07c4, 0xa4a5, 0x0000, 0xffff,
+               "Simple Tech/Datafab",
+               "CF+SM Reader",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_IGNORE_RESIDUE ),
+
 /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
  * to the USB storage specification in two ways:
  * - They tell us they are using transport protocol CBI. In reality they
@@ -1562,6 +1576,7 @@ UNUSUAL_DEV(  0x10d6, 0x2200, 0x0100, 0x0100,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                0),
 
+#ifdef CONFIG_USB_STORAGE_SIERRA
 /* Reported by Kevin Lloyd <linux@sierrawireless.com>
  * Entry is needed for the initializer function override,
  * which instructs the device to load as a modem
@@ -1570,8 +1585,9 @@ UNUSUAL_DEV(  0x10d6, 0x2200, 0x0100, 0x0100,
 UNUSUAL_DEV(  0x1199, 0x0fff, 0x0000, 0x9999,
                "Sierra Wireless",
                "USB MMC Storage",
-               US_SC_DEVICE, US_PR_DEVICE, NULL,
-               US_FL_IGNORE_DEVICE),
+               US_SC_DEVICE, US_PR_DEVICE, sierra_ms_init,
+               0),
+#endif
 
 /* Reported by Jaco Kroon <jaco@kroon.co.za>
  * The usb-storage module found on the Digitech GNX4 (and supposedly other
@@ -1742,6 +1758,15 @@ UNUSUAL_DEV(  0x22b8, 0x4810, 0x0001, 0x0002,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY),
 
+/*
+ * Patch by Jost Diederichs <jost@qdusa.com>
+ */
+UNUSUAL_DEV(0x22b8, 0x6410, 0x0001, 0x9999,
+               "Motorola Inc.",
+               "Motorola Phone (RAZRV3xx)",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_CAPACITY),
+
 /*
  * Patch by Constantin Baranov <const@tltsu.ru>
  * Report by Andreas Koenecke.
@@ -1767,6 +1792,13 @@ UNUSUAL_DEV(  0x2770, 0x915d, 0x0010, 0x0010,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY ),
 
+/* Reported by Andrey Rahmatullin <wrar@altlinux.org> */
+UNUSUAL_DEV(  0x4102, 0x1020, 0x0100,  0x0100,
+               "iRiver",
+               "MP3 T10",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_IGNORE_RESIDUE ),
+
 /*
  * David Härdeman <david@2gen.com>
  * The key makes the SCSI stack print confusing (but harmless) messages
index bfea851be9850ff9662e9f2c647f196db18bdffc..73679aa506debe4a7b26cd33fd24fcbafbb6f1bf 100644 (file)
 #ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
 #include "cypress_atacb.h"
 #endif
+#ifdef CONFIG_USB_STORAGE_SIERRA
+#include "sierra_ms.h"
+#endif
 
 /* Some informational data */
 MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
index c4e7d721bd8dcffaedcbdf3fcac2b2ea5ac26c31..89d2fb7b991ae13f1ada96176a5dca785b9dd646 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
 
 static struct config_group *space_list;
 static struct config_group *comm_list;
-static struct comm *local_comm;
+static struct dlm_comm *local_comm;
 
-struct clusters;
-struct cluster;
-struct spaces;
-struct space;
-struct comms;
-struct comm;
-struct nodes;
-struct node;
+struct dlm_clusters;
+struct dlm_cluster;
+struct dlm_spaces;
+struct dlm_space;
+struct dlm_comms;
+struct dlm_comm;
+struct dlm_nodes;
+struct dlm_node;
 
 static struct config_group *make_cluster(struct config_group *, const char *);
 static void drop_cluster(struct config_group *, struct config_item *);
@@ -68,17 +68,22 @@ static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
 static ssize_t store_node(struct config_item *i, struct configfs_attribute *a,
                          const char *buf, size_t len);
 
-static ssize_t comm_nodeid_read(struct comm *cm, char *buf);
-static ssize_t comm_nodeid_write(struct comm *cm, const char *buf, size_t len);
-static ssize_t comm_local_read(struct comm *cm, char *buf);
-static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len);
-static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len);
-static ssize_t node_nodeid_read(struct node *nd, char *buf);
-static ssize_t node_nodeid_write(struct node *nd, const char *buf, size_t len);
-static ssize_t node_weight_read(struct node *nd, char *buf);
-static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len);
-
-struct cluster {
+static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf);
+static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
+                               size_t len);
+static ssize_t comm_local_read(struct dlm_comm *cm, char *buf);
+static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
+                               size_t len);
+static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf,
+                               size_t len);
+static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf);
+static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
+                               size_t len);
+static ssize_t node_weight_read(struct dlm_node *nd, char *buf);
+static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
+                               size_t len);
+
+struct dlm_cluster {
        struct config_group group;
        unsigned int cl_tcp_port;
        unsigned int cl_buffer_size;
@@ -109,11 +114,11 @@ enum {
 
 struct cluster_attribute {
        struct configfs_attribute attr;
-       ssize_t (*show)(struct cluster *, char *);
-       ssize_t (*store)(struct cluster *, const char *, size_t);
+       ssize_t (*show)(struct dlm_cluster *, char *);
+       ssize_t (*store)(struct dlm_cluster *, const char *, size_t);
 };
 
-static ssize_t cluster_set(struct cluster *cl, unsigned int *cl_field,
+static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
                           int *info_field, int check_zero,
                           const char *buf, size_t len)
 {
@@ -134,12 +139,12 @@ static ssize_t cluster_set(struct cluster *cl, unsigned int *cl_field,
 }
 
 #define CLUSTER_ATTR(name, check_zero)                                        \
-static ssize_t name##_write(struct cluster *cl, const char *buf, size_t len)  \
+static ssize_t name##_write(struct dlm_cluster *cl, const char *buf, size_t len) \
 {                                                                             \
        return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name,         \
                           check_zero, buf, len);                             \
 }                                                                             \
-static ssize_t name##_read(struct cluster *cl, char *buf)                     \
+static ssize_t name##_read(struct dlm_cluster *cl, char *buf)                 \
 {                                                                             \
        return snprintf(buf, PAGE_SIZE, "%u\n", cl->cl_##name);               \
 }                                                                             \
@@ -181,8 +186,8 @@ enum {
 
 struct comm_attribute {
        struct configfs_attribute attr;
-       ssize_t (*show)(struct comm *, char *);
-       ssize_t (*store)(struct comm *, const char *, size_t);
+       ssize_t (*show)(struct dlm_comm *, char *);
+       ssize_t (*store)(struct dlm_comm *, const char *, size_t);
 };
 
 static struct comm_attribute comm_attr_nodeid = {
@@ -222,8 +227,8 @@ enum {
 
 struct node_attribute {
        struct configfs_attribute attr;
-       ssize_t (*show)(struct node *, char *);
-       ssize_t (*store)(struct node *, const char *, size_t);
+       ssize_t (*show)(struct dlm_node *, char *);
+       ssize_t (*store)(struct dlm_node *, const char *, size_t);
 };
 
 static struct node_attribute node_attr_nodeid = {
@@ -248,26 +253,26 @@ static struct configfs_attribute *node_attrs[] = {
        NULL,
 };
 
-struct clusters {
+struct dlm_clusters {
        struct configfs_subsystem subsys;
 };
 
-struct spaces {
+struct dlm_spaces {
        struct config_group ss_group;
 };
 
-struct space {
+struct dlm_space {
        struct config_group group;
        struct list_head members;
        struct mutex members_lock;
        int members_count;
 };
 
-struct comms {
+struct dlm_comms {
        struct config_group cs_group;
 };
 
-struct comm {
+struct dlm_comm {
        struct config_item item;
        int nodeid;
        int local;
@@ -275,11 +280,11 @@ struct comm {
        struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT];
 };
 
-struct nodes {
+struct dlm_nodes {
        struct config_group ns_group;
 };
 
-struct node {
+struct dlm_node {
        struct config_item item;
        struct list_head list; /* space->members */
        int nodeid;
@@ -372,38 +377,40 @@ static struct config_item_type node_type = {
        .ct_owner = THIS_MODULE,
 };
 
-static struct cluster *to_cluster(struct config_item *i)
+static struct dlm_cluster *to_cluster(struct config_item *i)
 {
-       return i ? container_of(to_config_group(i), struct cluster, group):NULL;
+       return i ? container_of(to_config_group(i), struct dlm_cluster, group) :
+                  NULL;
 }
 
-static struct space *to_space(struct config_item *i)
+static struct dlm_space *to_space(struct config_item *i)
 {
-       return i ? container_of(to_config_group(i), struct space, group) : NULL;
+       return i ? container_of(to_config_group(i), struct dlm_space, group) :
+                  NULL;
 }
 
-static struct comm *to_comm(struct config_item *i)
+static struct dlm_comm *to_comm(struct config_item *i)
 {
-       return i ? container_of(i, struct comm, item) : NULL;
+       return i ? container_of(i, struct dlm_comm, item) : NULL;
 }
 
-static struct node *to_node(struct config_item *i)
+static struct dlm_node *to_node(struct config_item *i)
 {
-       return i ? container_of(i, struct node, item) : NULL;
+       return i ? container_of(i, struct dlm_node, item) : NULL;
 }
 
 static struct config_group *make_cluster(struct config_group *g,
                                         const char *name)
 {
-       struct cluster *cl = NULL;
-       struct spaces *sps = NULL;
-       struct comms *cms = NULL;
+       struct dlm_cluster *cl = NULL;
+       struct dlm_spaces *sps = NULL;
+       struct dlm_comms *cms = NULL;
        void *gps = NULL;
 
-       cl = kzalloc(sizeof(struct cluster), GFP_KERNEL);
+       cl = kzalloc(sizeof(struct dlm_cluster), GFP_KERNEL);
        gps = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL);
-       sps = kzalloc(sizeof(struct spaces), GFP_KERNEL);
-       cms = kzalloc(sizeof(struct comms), GFP_KERNEL);
+       sps = kzalloc(sizeof(struct dlm_spaces), GFP_KERNEL);
+       cms = kzalloc(sizeof(struct dlm_comms), GFP_KERNEL);
 
        if (!cl || !gps || !sps || !cms)
                goto fail;
@@ -443,7 +450,7 @@ static struct config_group *make_cluster(struct config_group *g,
 
 static void drop_cluster(struct config_group *g, struct config_item *i)
 {
-       struct cluster *cl = to_cluster(i);
+       struct dlm_cluster *cl = to_cluster(i);
        struct config_item *tmp;
        int j;
 
@@ -461,20 +468,20 @@ static void drop_cluster(struct config_group *g, struct config_item *i)
 
 static void release_cluster(struct config_item *i)
 {
-       struct cluster *cl = to_cluster(i);
+       struct dlm_cluster *cl = to_cluster(i);
        kfree(cl->group.default_groups);
        kfree(cl);
 }
 
 static struct config_group *make_space(struct config_group *g, const char *name)
 {
-       struct space *sp = NULL;
-       struct nodes *nds = NULL;
+       struct dlm_space *sp = NULL;
+       struct dlm_nodes *nds = NULL;
        void *gps = NULL;
 
-       sp = kzalloc(sizeof(struct space), GFP_KERNEL);
+       sp = kzalloc(sizeof(struct dlm_space), GFP_KERNEL);
        gps = kcalloc(2, sizeof(struct config_group *), GFP_KERNEL);
-       nds = kzalloc(sizeof(struct nodes), GFP_KERNEL);
+       nds = kzalloc(sizeof(struct dlm_nodes), GFP_KERNEL);
 
        if (!sp || !gps || !nds)
                goto fail;
@@ -500,7 +507,7 @@ static struct config_group *make_space(struct config_group *g, const char *name)
 
 static void drop_space(struct config_group *g, struct config_item *i)
 {
-       struct space *sp = to_space(i);
+       struct dlm_space *sp = to_space(i);
        struct config_item *tmp;
        int j;
 
@@ -517,16 +524,16 @@ static void drop_space(struct config_group *g, struct config_item *i)
 
 static void release_space(struct config_item *i)
 {
-       struct space *sp = to_space(i);
+       struct dlm_space *sp = to_space(i);
        kfree(sp->group.default_groups);
        kfree(sp);
 }
 
 static struct config_item *make_comm(struct config_group *g, const char *name)
 {
-       struct comm *cm;
+       struct dlm_comm *cm;
 
-       cm = kzalloc(sizeof(struct comm), GFP_KERNEL);
+       cm = kzalloc(sizeof(struct dlm_comm), GFP_KERNEL);
        if (!cm)
                return ERR_PTR(-ENOMEM);
 
@@ -539,7 +546,7 @@ static struct config_item *make_comm(struct config_group *g, const char *name)
 
 static void drop_comm(struct config_group *g, struct config_item *i)
 {
-       struct comm *cm = to_comm(i);
+       struct dlm_comm *cm = to_comm(i);
        if (local_comm == cm)
                local_comm = NULL;
        dlm_lowcomms_close(cm->nodeid);
@@ -550,16 +557,16 @@ static void drop_comm(struct config_group *g, struct config_item *i)
 
 static void release_comm(struct config_item *i)
 {
-       struct comm *cm = to_comm(i);
+       struct dlm_comm *cm = to_comm(i);
        kfree(cm);
 }
 
 static struct config_item *make_node(struct config_group *g, const char *name)
 {
-       struct space *sp = to_space(g->cg_item.ci_parent);
-       struct node *nd;
+       struct dlm_space *sp = to_space(g->cg_item.ci_parent);
+       struct dlm_node *nd;
 
-       nd = kzalloc(sizeof(struct node), GFP_KERNEL);
+       nd = kzalloc(sizeof(struct dlm_node), GFP_KERNEL);
        if (!nd)
                return ERR_PTR(-ENOMEM);
 
@@ -578,8 +585,8 @@ static struct config_item *make_node(struct config_group *g, const char *name)
 
 static void drop_node(struct config_group *g, struct config_item *i)
 {
-       struct space *sp = to_space(g->cg_item.ci_parent);
-       struct node *nd = to_node(i);
+       struct dlm_space *sp = to_space(g->cg_item.ci_parent);
+       struct dlm_node *nd = to_node(i);
 
        mutex_lock(&sp->members_lock);
        list_del(&nd->list);
@@ -591,11 +598,11 @@ static void drop_node(struct config_group *g, struct config_item *i)
 
 static void release_node(struct config_item *i)
 {
-       struct node *nd = to_node(i);
+       struct dlm_node *nd = to_node(i);
        kfree(nd);
 }
 
-static struct clusters clusters_root = {
+static struct dlm_clusters clusters_root = {
        .subsys = {
                .su_group = {
                        .cg_item = {
@@ -625,7 +632,7 @@ void dlm_config_exit(void)
 static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
                            char *buf)
 {
-       struct cluster *cl = to_cluster(i);
+       struct dlm_cluster *cl = to_cluster(i);
        struct cluster_attribute *cla =
                        container_of(a, struct cluster_attribute, attr);
        return cla->show ? cla->show(cl, buf) : 0;
@@ -635,7 +642,7 @@ static ssize_t store_cluster(struct config_item *i,
                             struct configfs_attribute *a,
                             const char *buf, size_t len)
 {
-       struct cluster *cl = to_cluster(i);
+       struct dlm_cluster *cl = to_cluster(i);
        struct cluster_attribute *cla =
                container_of(a, struct cluster_attribute, attr);
        return cla->store ? cla->store(cl, buf, len) : -EINVAL;
@@ -644,7 +651,7 @@ static ssize_t store_cluster(struct config_item *i,
 static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
                         char *buf)
 {
-       struct comm *cm = to_comm(i);
+       struct dlm_comm *cm = to_comm(i);
        struct comm_attribute *cma =
                        container_of(a, struct comm_attribute, attr);
        return cma->show ? cma->show(cm, buf) : 0;
@@ -653,29 +660,31 @@ static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
 static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a,
                          const char *buf, size_t len)
 {
-       struct comm *cm = to_comm(i);
+       struct dlm_comm *cm = to_comm(i);
        struct comm_attribute *cma =
                container_of(a, struct comm_attribute, attr);
        return cma->store ? cma->store(cm, buf, len) : -EINVAL;
 }
 
-static ssize_t comm_nodeid_read(struct comm *cm, char *buf)
+static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf)
 {
        return sprintf(buf, "%d\n", cm->nodeid);
 }
 
-static ssize_t comm_nodeid_write(struct comm *cm, const char *buf, size_t len)
+static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
+                                size_t len)
 {
        cm->nodeid = simple_strtol(buf, NULL, 0);
        return len;
 }
 
-static ssize_t comm_local_read(struct comm *cm, char *buf)
+static ssize_t comm_local_read(struct dlm_comm *cm, char *buf)
 {
        return sprintf(buf, "%d\n", cm->local);
 }
 
-static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len)
+static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
+                               size_t len)
 {
        cm->local= simple_strtol(buf, NULL, 0);
        if (cm->local && !local_comm)
@@ -683,7 +692,7 @@ static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len)
        return len;
 }
 
-static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len)
+static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
 {
        struct sockaddr_storage *addr;
 
@@ -705,7 +714,7 @@ static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len)
 static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
                         char *buf)
 {
-       struct node *nd = to_node(i);
+       struct dlm_node *nd = to_node(i);
        struct node_attribute *nda =
                        container_of(a, struct node_attribute, attr);
        return nda->show ? nda->show(nd, buf) : 0;
@@ -714,29 +723,31 @@ static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
 static ssize_t store_node(struct config_item *i, struct configfs_attribute *a,
                          const char *buf, size_t len)
 {
-       struct node *nd = to_node(i);
+       struct dlm_node *nd = to_node(i);
        struct node_attribute *nda =
                container_of(a, struct node_attribute, attr);
        return nda->store ? nda->store(nd, buf, len) : -EINVAL;
 }
 
-static ssize_t node_nodeid_read(struct node *nd, char *buf)
+static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf)
 {
        return sprintf(buf, "%d\n", nd->nodeid);
 }
 
-static ssize_t node_nodeid_write(struct node *nd, const char *buf, size_t len)
+static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
+                                size_t len)
 {
        nd->nodeid = simple_strtol(buf, NULL, 0);
        return len;
 }
 
-static ssize_t node_weight_read(struct node *nd, char *buf)
+static ssize_t node_weight_read(struct dlm_node *nd, char *buf)
 {
        return sprintf(buf, "%d\n", nd->weight);
 }
 
-static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len)
+static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
+                                size_t len)
 {
        nd->weight = simple_strtol(buf, NULL, 0);
        return len;
@@ -746,7 +757,7 @@ static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len)
  * Functions for the dlm to get the info that's been configured
  */
 
-static struct space *get_space(char *name)
+static struct dlm_space *get_space(char *name)
 {
        struct config_item *i;
 
@@ -760,15 +771,15 @@ static struct space *get_space(char *name)
        return to_space(i);
 }
 
-static void put_space(struct space *sp)
+static void put_space(struct dlm_space *sp)
 {
        config_item_put(&sp->group.cg_item);
 }
 
-static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr)
+static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr)
 {
        struct config_item *i;
-       struct comm *cm = NULL;
+       struct dlm_comm *cm = NULL;
        int found = 0;
 
        if (!comm_list)
@@ -801,7 +812,7 @@ static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr)
        return cm;
 }
 
-static void put_comm(struct comm *cm)
+static void put_comm(struct dlm_comm *cm)
 {
        config_item_put(&cm->item);
 }
@@ -810,8 +821,8 @@ static void put_comm(struct comm *cm)
 int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
                    int **new_out, int *new_count_out)
 {
-       struct space *sp;
-       struct node *nd;
+       struct dlm_space *sp;
+       struct dlm_node *nd;
        int i = 0, rv = 0, ids_count = 0, new_count = 0;
        int *ids, *new;
 
@@ -874,8 +885,8 @@ int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
 
 int dlm_node_weight(char *lsname, int nodeid)
 {
-       struct space *sp;
-       struct node *nd;
+       struct dlm_space *sp;
+       struct dlm_node *nd;
        int w = -EEXIST;
 
        sp = get_space(lsname);
@@ -897,7 +908,7 @@ int dlm_node_weight(char *lsname, int nodeid)
 
 int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr)
 {
-       struct comm *cm = get_comm(nodeid, NULL);
+       struct dlm_comm *cm = get_comm(nodeid, NULL);
        if (!cm)
                return -EEXIST;
        if (!cm->addr_count)
@@ -909,7 +920,7 @@ int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr)
 
 int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid)
 {
-       struct comm *cm = get_comm(0, addr);
+       struct dlm_comm *cm = get_comm(0, addr);
        if (!cm)
                return -EEXIST;
        *nodeid = cm->nodeid;
index 929e48ae7591199cc0e6e4c80eb4516c939bfd60..34f14a14fb4e41e0e8b5b8a0ed207f7f37976703 100644 (file)
@@ -527,8 +527,10 @@ static ssize_t device_write(struct file *file, const char __user *buf,
                k32buf = (struct dlm_write_request32 *)kbuf;
                kbuf = kmalloc(count + 1 + (sizeof(struct dlm_write_request) -
                               sizeof(struct dlm_write_request32)), GFP_KERNEL);
-               if (!kbuf)
+               if (!kbuf) {
+                       kfree(k32buf);
                        return -ENOMEM;
+               }
 
                if (proc)
                        set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
@@ -539,8 +541,10 @@ static ssize_t device_write(struct file *file, const char __user *buf,
 
        /* do we really need this? can a write happen after a close? */
        if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) &&
-           (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags)))
-               return -EINVAL;
+           (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))) {
+               error = -EINVAL;
+               goto out_free;
+       }
 
        sigfillset(&allsigs);
        sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
diff --git a/fs/xfs/linux-2.6/sema.h b/fs/xfs/linux-2.6/sema.h
deleted file mode 100644 (file)
index 3abe7e9..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_SUPPORT_SEMA_H__
-#define __XFS_SUPPORT_SEMA_H__
-
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <linux/semaphore.h>
-#include <asm/atomic.h>
-
-/*
- * sema_t structure just maps to struct semaphore in Linux kernel.
- */
-
-typedef struct semaphore sema_t;
-
-#define initnsema(sp, val, name)       sema_init(sp, val)
-#define psema(sp, b)                   down(sp)
-#define vsema(sp)                      up(sp)
-#define freesema(sema)                 do { } while (0)
-
-static inline int issemalocked(sema_t *sp)
-{
-       return down_trylock(sp) || (up(sp), 0);
-}
-
-/*
- * Map cpsema (try to get the sema) to down_trylock. We need to switch
- * the return values since cpsema returns 1 (acquired) 0 (failed) and
- * down_trylock returns the reverse 0 (acquired) 1 (failed).
- */
-static inline int cpsema(sema_t *sp)
-{
-       return down_trylock(sp) ? 0 : 1;
-}
-
-#endif /* __XFS_SUPPORT_SEMA_H__ */
index fa47e43b8b41a525843c57cb4591ed9ffd334141..f42f80a3b1faca317f3e08b021c532f19e0512cc 100644 (file)
@@ -73,7 +73,6 @@ xfs_page_trace(
        unsigned long   pgoff)
 {
        xfs_inode_t     *ip;
-       bhv_vnode_t     *vp = vn_from_inode(inode);
        loff_t          isize = i_size_read(inode);
        loff_t          offset = page_offset(page);
        int             delalloc = -1, unmapped = -1, unwritten = -1;
@@ -81,7 +80,7 @@ xfs_page_trace(
        if (page_has_buffers(page))
                xfs_count_page_state(page, &delalloc, &unmapped, &unwritten);
 
-       ip = xfs_vtoi(vp);
+       ip = XFS_I(inode);
        if (!ip->i_rwtrace)
                return;
 
index 9cc8f0213095b92e868fa396b099bc13c2a2ec47..986061ae1b9b18f1e22220e04b0db715a79c3dd6 100644 (file)
@@ -58,7 +58,7 @@ xfs_buf_trace(
                bp, id,
                (void *)(unsigned long)bp->b_flags,
                (void *)(unsigned long)bp->b_hold.counter,
-               (void *)(unsigned long)bp->b_sema.count.counter,
+               (void *)(unsigned long)bp->b_sema.count,
                (void *)current,
                data, ra,
                (void *)(unsigned long)((bp->b_file_offset>>32) & 0xffffffff),
@@ -253,7 +253,7 @@ _xfs_buf_initialize(
 
        memset(bp, 0, sizeof(xfs_buf_t));
        atomic_set(&bp->b_hold, 1);
-       init_MUTEX_LOCKED(&bp->b_iodonesema);
+       init_completion(&bp->b_iowait);
        INIT_LIST_HEAD(&bp->b_list);
        INIT_LIST_HEAD(&bp->b_hash_list);
        init_MUTEX_LOCKED(&bp->b_sema); /* held, no waiters */
@@ -838,6 +838,7 @@ xfs_buf_rele(
                return;
        }
 
+       ASSERT(atomic_read(&bp->b_hold) > 0);
        if (atomic_dec_and_lock(&bp->b_hold, &hash->bh_lock)) {
                if (bp->b_relse) {
                        atomic_inc(&bp->b_hold);
@@ -851,11 +852,6 @@ xfs_buf_rele(
                        spin_unlock(&hash->bh_lock);
                        xfs_buf_free(bp);
                }
-       } else {
-               /*
-                * Catch reference count leaks
-                */
-               ASSERT(atomic_read(&bp->b_hold) >= 0);
        }
 }
 
@@ -1037,7 +1033,7 @@ xfs_buf_ioend(
                        xfs_buf_iodone_work(&bp->b_iodone_work);
                }
        } else {
-               up(&bp->b_iodonesema);
+               complete(&bp->b_iowait);
        }
 }
 
@@ -1275,7 +1271,7 @@ xfs_buf_iowait(
        XB_TRACE(bp, "iowait", 0);
        if (atomic_read(&bp->b_io_remaining))
                blk_run_address_space(bp->b_target->bt_mapping);
-       down(&bp->b_iodonesema);
+       wait_for_completion(&bp->b_iowait);
        XB_TRACE(bp, "iowaited", (long)bp->b_error);
        return bp->b_error;
 }
@@ -1799,7 +1795,7 @@ int __init
 xfs_buf_init(void)
 {
 #ifdef XFS_BUF_TRACE
-       xfs_buf_trace_buf = ktrace_alloc(XFS_BUF_TRACE_SIZE, KM_SLEEP);
+       xfs_buf_trace_buf = ktrace_alloc(XFS_BUF_TRACE_SIZE, KM_NOFS);
 #endif
 
        xfs_buf_zone = kmem_zone_init_flags(sizeof(xfs_buf_t), "xfs_buf",
index 29d1d4adc07897a7fdb47b76b4deb9fbf4c78e27..fe01099566564d0a3dc9cedc850c9874d41bdc6a 100644 (file)
@@ -157,7 +157,7 @@ typedef struct xfs_buf {
        xfs_buf_iodone_t        b_iodone;       /* I/O completion function */
        xfs_buf_relse_t         b_relse;        /* releasing function */
        xfs_buf_bdstrat_t       b_strat;        /* pre-write function */
-       struct semaphore        b_iodonesema;   /* Semaphore for I/O waiters */
+       struct completion       b_iowait;       /* queue for I/O waiters */
        void                    *b_fspriv;
        void                    *b_fspriv2;
        void                    *b_fspriv3;
@@ -352,7 +352,7 @@ extern void xfs_buf_trace(xfs_buf_t *, char *, void *, void *);
 #define XFS_BUF_CPSEMA(bp)     (xfs_buf_cond_lock(bp) == 0)
 #define XFS_BUF_VSEMA(bp)      xfs_buf_unlock(bp)
 #define XFS_BUF_PSEMA(bp,x)    xfs_buf_lock(bp)
-#define XFS_BUF_V_IODONESEMA(bp) up(&bp->b_iodonesema);
+#define XFS_BUF_FINISH_IOWAIT(bp)      complete(&bp->b_iowait);
 
 #define XFS_BUF_SET_TARGET(bp, target) ((bp)->b_target = (target))
 #define XFS_BUF_TARGET(bp)             ((bp)->b_target)
index 987fe84f7b1351d8204b18d182c4f49185f95218..24fd598af84633876a169e7887818ac7742238fd 100644 (file)
@@ -139,7 +139,7 @@ xfs_nfs_get_inode(
        }
 
        xfs_iunlock(ip, XFS_ILOCK_SHARED);
-       return ip->i_vnode;
+       return VFS_I(ip);
 }
 
 STATIC struct dentry *
@@ -167,7 +167,7 @@ xfs_fs_fh_to_dentry(struct super_block *sb, struct fid *fid,
        if (!inode)
                return NULL;
        if (IS_ERR(inode))
-               return ERR_PTR(PTR_ERR(inode));
+               return ERR_CAST(inode);
        result = d_alloc_anon(inode);
        if (!result) {
                iput(inode);
@@ -198,7 +198,7 @@ xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid,
        if (!inode)
                return NULL;
        if (IS_ERR(inode))
-               return ERR_PTR(PTR_ERR(inode));
+               return ERR_CAST(inode);
        result = d_alloc_anon(inode);
        if (!result) {
                iput(inode);
@@ -219,9 +219,9 @@ xfs_fs_get_parent(
        if (unlikely(error))
                return ERR_PTR(-error);
 
-       parent = d_alloc_anon(cip->i_vnode);
+       parent = d_alloc_anon(VFS_I(cip));
        if (unlikely(!parent)) {
-               iput(cip->i_vnode);
+               iput(VFS_I(cip));
                return ERR_PTR(-ENOMEM);
        }
        return parent;
index 1eefe61f0e10baa80a68c416b7e4f92dba816538..36caa6d957dfd035687e51511622f07366b4c259 100644 (file)
@@ -31,7 +31,7 @@ xfs_tosspages(
        xfs_off_t       last,
        int             fiopt)
 {
-       struct address_space *mapping = ip->i_vnode->i_mapping;
+       struct address_space *mapping = VFS_I(ip)->i_mapping;
 
        if (mapping->nrpages)
                truncate_inode_pages(mapping, first);
@@ -44,7 +44,7 @@ xfs_flushinval_pages(
        xfs_off_t       last,
        int             fiopt)
 {
-       struct address_space *mapping = ip->i_vnode->i_mapping;
+       struct address_space *mapping = VFS_I(ip)->i_mapping;
        int             ret = 0;
 
        if (mapping->nrpages) {
@@ -64,7 +64,7 @@ xfs_flush_pages(
        uint64_t        flags,
        int             fiopt)
 {
-       struct address_space *mapping = ip->i_vnode->i_mapping;
+       struct address_space *mapping = VFS_I(ip)->i_mapping;
        int             ret = 0;
        int             ret2;
 
index acb978d9d0859a17a5518dc544d6165c250288f5..48799ba7e3e6f2ded6a46e972a254044c76bb83d 100644 (file)
@@ -245,7 +245,7 @@ xfs_vget_fsop_handlereq(
 
        xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
-       *inode = XFS_ITOV(ip);
+       *inode = VFS_I(ip);
        return 0;
 }
 
@@ -927,7 +927,7 @@ STATIC void
 xfs_diflags_to_linux(
        struct xfs_inode        *ip)
 {
-       struct inode            *inode = XFS_ITOV(ip);
+       struct inode            *inode = VFS_I(ip);
        unsigned int            xflags = xfs_ip2xflags(ip);
 
        if (xflags & XFS_XFLAG_IMMUTABLE)
index e88f51028086796d0ce80a7f47a88e0c953b72bd..91bcd979242cc1dc05b1a0b4bd34e13ec5925b7c 100644 (file)
@@ -62,7 +62,7 @@ void
 xfs_synchronize_atime(
        xfs_inode_t     *ip)
 {
-       struct inode    *inode = ip->i_vnode;
+       struct inode    *inode = VFS_I(ip);
 
        if (inode) {
                ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
@@ -79,7 +79,7 @@ void
 xfs_mark_inode_dirty_sync(
        xfs_inode_t     *ip)
 {
-       struct inode    *inode = ip->i_vnode;
+       struct inode    *inode = VFS_I(ip);
 
        if (inode)
                mark_inode_dirty_sync(inode);
@@ -89,36 +89,31 @@ xfs_mark_inode_dirty_sync(
  * Change the requested timestamp in the given inode.
  * We don't lock across timestamp updates, and we don't log them but
  * we do record the fact that there is dirty information in core.
- *
- * NOTE -- callers MUST combine XFS_ICHGTIME_MOD or XFS_ICHGTIME_CHG
- *             with XFS_ICHGTIME_ACC to be sure that access time
- *             update will take.  Calling first with XFS_ICHGTIME_ACC
- *             and then XFS_ICHGTIME_MOD may fail to modify the access
- *             timestamp if the filesystem is mounted noacctm.
  */
 void
 xfs_ichgtime(
        xfs_inode_t     *ip,
        int             flags)
 {
-       struct inode    *inode = vn_to_inode(XFS_ITOV(ip));
+       struct inode    *inode = VFS_I(ip);
        timespec_t      tv;
+       int             sync_it = 0;
+
+       tv = current_fs_time(inode->i_sb);
 
-       nanotime(&tv);
-       if (flags & XFS_ICHGTIME_MOD) {
+       if ((flags & XFS_ICHGTIME_MOD) &&
+           !timespec_equal(&inode->i_mtime, &tv)) {
                inode->i_mtime = tv;
                ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
                ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
+               sync_it = 1;
        }
-       if (flags & XFS_ICHGTIME_ACC) {
-               inode->i_atime = tv;
-               ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec;
-               ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec;
-       }
-       if (flags & XFS_ICHGTIME_CHG) {
+       if ((flags & XFS_ICHGTIME_CHG) &&
+           !timespec_equal(&inode->i_ctime, &tv)) {
                inode->i_ctime = tv;
                ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;
                ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;
+               sync_it = 1;
        }
 
        /*
@@ -130,55 +125,11 @@ xfs_ichgtime(
         * ensure that the compiler does not reorder the update
         * of i_update_core above the timestamp updates above.
         */
-       SYNCHRONIZE();
-       ip->i_update_core = 1;
-       if (!(inode->i_state & I_NEW))
+       if (sync_it) {
+               SYNCHRONIZE();
+               ip->i_update_core = 1;
                mark_inode_dirty_sync(inode);
-}
-
-/*
- * Variant on the above which avoids querying the system clock
- * in situations where we know the Linux inode timestamps have
- * just been updated (and so we can update our inode cheaply).
- */
-void
-xfs_ichgtime_fast(
-       xfs_inode_t     *ip,
-       struct inode    *inode,
-       int             flags)
-{
-       timespec_t      *tvp;
-
-       /*
-        * Atime updates for read() & friends are handled lazily now, and
-        * explicit updates must go through xfs_ichgtime()
-        */
-       ASSERT((flags & XFS_ICHGTIME_ACC) == 0);
-
-       if (flags & XFS_ICHGTIME_MOD) {
-               tvp = &inode->i_mtime;
-               ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec;
-               ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec;
        }
-       if (flags & XFS_ICHGTIME_CHG) {
-               tvp = &inode->i_ctime;
-               ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec;
-               ip->i_d.di_ctime.t_nsec = (__int32_t)tvp->tv_nsec;
-       }
-
-       /*
-        * We update the i_update_core field _after_ changing
-        * the timestamps in order to coordinate properly with
-        * xfs_iflush() so that we don't lose timestamp updates.
-        * This keeps us from having to hold the inode lock
-        * while doing this.  We use the SYNCHRONIZE macro to
-        * ensure that the compiler does not reorder the update
-        * of i_update_core above the timestamp updates above.
-        */
-       SYNCHRONIZE();
-       ip->i_update_core = 1;
-       if (!(inode->i_state & I_NEW))
-               mark_inode_dirty_sync(inode);
 }
 
 /*
@@ -299,7 +250,7 @@ xfs_vn_mknod(
        if (unlikely(error))
                goto out_free_acl;
 
-       inode = ip->i_vnode;
+       inode = VFS_I(ip);
 
        error = xfs_init_security(inode, dir);
        if (unlikely(error))
@@ -366,7 +317,7 @@ xfs_vn_lookup(
                return NULL;
        }
 
-       return d_splice_alias(cip->i_vnode, dentry);
+       return d_splice_alias(VFS_I(cip), dentry);
 }
 
 STATIC struct dentry *
@@ -399,12 +350,12 @@ xfs_vn_ci_lookup(
 
        /* if exact match, just splice and exit */
        if (!ci_name.name)
-               return d_splice_alias(ip->i_vnode, dentry);
+               return d_splice_alias(VFS_I(ip), dentry);
 
        /* else case-insensitive match... */
        dname.name = ci_name.name;
        dname.len = ci_name.len;
-       dentry = d_add_ci(ip->i_vnode, dentry, &dname);
+       dentry = d_add_ci(VFS_I(ip), dentry, &dname);
        kmem_free(ci_name.name);
        return dentry;
 }
@@ -478,7 +429,7 @@ xfs_vn_symlink(
        if (unlikely(error))
                goto out;
 
-       inode = cip->i_vnode;
+       inode = VFS_I(cip);
 
        error = xfs_init_security(inode, dir);
        if (unlikely(error))
@@ -710,7 +661,7 @@ out_error:
        return error;
 }
 
-const struct inode_operations xfs_inode_operations = {
+static const struct inode_operations xfs_inode_operations = {
        .permission             = xfs_vn_permission,
        .truncate               = xfs_vn_truncate,
        .getattr                = xfs_vn_getattr,
@@ -722,7 +673,7 @@ const struct inode_operations xfs_inode_operations = {
        .fallocate              = xfs_vn_fallocate,
 };
 
-const struct inode_operations xfs_dir_inode_operations = {
+static const struct inode_operations xfs_dir_inode_operations = {
        .create                 = xfs_vn_create,
        .lookup                 = xfs_vn_lookup,
        .link                   = xfs_vn_link,
@@ -747,7 +698,7 @@ const struct inode_operations xfs_dir_inode_operations = {
        .listxattr              = xfs_vn_listxattr,
 };
 
-const struct inode_operations xfs_dir_ci_inode_operations = {
+static const struct inode_operations xfs_dir_ci_inode_operations = {
        .create                 = xfs_vn_create,
        .lookup                 = xfs_vn_ci_lookup,
        .link                   = xfs_vn_link,
@@ -772,7 +723,7 @@ const struct inode_operations xfs_dir_ci_inode_operations = {
        .listxattr              = xfs_vn_listxattr,
 };
 
-const struct inode_operations xfs_symlink_inode_operations = {
+static const struct inode_operations xfs_symlink_inode_operations = {
        .readlink               = generic_readlink,
        .follow_link            = xfs_vn_follow_link,
        .put_link               = xfs_vn_put_link,
@@ -784,3 +735,98 @@ const struct inode_operations xfs_symlink_inode_operations = {
        .removexattr            = generic_removexattr,
        .listxattr              = xfs_vn_listxattr,
 };
+
+STATIC void
+xfs_diflags_to_iflags(
+       struct inode            *inode,
+       struct xfs_inode        *ip)
+{
+       if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE)
+               inode->i_flags |= S_IMMUTABLE;
+       else
+               inode->i_flags &= ~S_IMMUTABLE;
+       if (ip->i_d.di_flags & XFS_DIFLAG_APPEND)
+               inode->i_flags |= S_APPEND;
+       else
+               inode->i_flags &= ~S_APPEND;
+       if (ip->i_d.di_flags & XFS_DIFLAG_SYNC)
+               inode->i_flags |= S_SYNC;
+       else
+               inode->i_flags &= ~S_SYNC;
+       if (ip->i_d.di_flags & XFS_DIFLAG_NOATIME)
+               inode->i_flags |= S_NOATIME;
+       else
+               inode->i_flags &= ~S_NOATIME;
+}
+
+/*
+ * Initialize the Linux inode, set up the operation vectors and
+ * unlock the inode.
+ *
+ * When reading existing inodes from disk this is called directly
+ * from xfs_iget, when creating a new inode it is called from
+ * xfs_ialloc after setting up the inode.
+ */
+void
+xfs_setup_inode(
+       struct xfs_inode        *ip)
+{
+       struct inode            *inode = ip->i_vnode;
+
+       inode->i_mode   = ip->i_d.di_mode;
+       inode->i_nlink  = ip->i_d.di_nlink;
+       inode->i_uid    = ip->i_d.di_uid;
+       inode->i_gid    = ip->i_d.di_gid;
+
+       switch (inode->i_mode & S_IFMT) {
+       case S_IFBLK:
+       case S_IFCHR:
+               inode->i_rdev =
+                       MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff,
+                             sysv_minor(ip->i_df.if_u2.if_rdev));
+               break;
+       default:
+               inode->i_rdev = 0;
+               break;
+       }
+
+       inode->i_generation = ip->i_d.di_gen;
+       i_size_write(inode, ip->i_d.di_size);
+       inode->i_atime.tv_sec   = ip->i_d.di_atime.t_sec;
+       inode->i_atime.tv_nsec  = ip->i_d.di_atime.t_nsec;
+       inode->i_mtime.tv_sec   = ip->i_d.di_mtime.t_sec;
+       inode->i_mtime.tv_nsec  = ip->i_d.di_mtime.t_nsec;
+       inode->i_ctime.tv_sec   = ip->i_d.di_ctime.t_sec;
+       inode->i_ctime.tv_nsec  = ip->i_d.di_ctime.t_nsec;
+       xfs_diflags_to_iflags(inode, ip);
+       xfs_iflags_clear(ip, XFS_IMODIFIED);
+
+       switch (inode->i_mode & S_IFMT) {
+       case S_IFREG:
+               inode->i_op = &xfs_inode_operations;
+               inode->i_fop = &xfs_file_operations;
+               inode->i_mapping->a_ops = &xfs_address_space_operations;
+               break;
+       case S_IFDIR:
+               if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb))
+                       inode->i_op = &xfs_dir_ci_inode_operations;
+               else
+                       inode->i_op = &xfs_dir_inode_operations;
+               inode->i_fop = &xfs_dir_file_operations;
+               break;
+       case S_IFLNK:
+               inode->i_op = &xfs_symlink_inode_operations;
+               if (!(ip->i_df.if_flags & XFS_IFINLINE))
+                       inode->i_mapping->a_ops = &xfs_address_space_operations;
+               break;
+       default:
+               inode->i_op = &xfs_inode_operations;
+               init_special_inode(inode, inode->i_mode, inode->i_rdev);
+               break;
+       }
+
+       xfs_iflags_clear(ip, XFS_INEW);
+       barrier();
+
+       unlock_new_inode(inode);
+}
index d97ba934a2ac8df74ff3a07cf18f7ad4cd53ddc0..8b1a1e31dc21f8c3414ee96c8285c2f54e81cc9c 100644 (file)
 #ifndef __XFS_IOPS_H__
 #define __XFS_IOPS_H__
 
-extern const struct inode_operations xfs_inode_operations;
-extern const struct inode_operations xfs_dir_inode_operations;
-extern const struct inode_operations xfs_dir_ci_inode_operations;
-extern const struct inode_operations xfs_symlink_inode_operations;
+struct xfs_inode;
 
 extern const struct file_operations xfs_file_operations;
 extern const struct file_operations xfs_dir_file_operations;
@@ -29,14 +26,6 @@ extern const struct file_operations xfs_invis_file_operations;
 
 extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size);
 
-struct xfs_inode;
-extern void xfs_ichgtime(struct xfs_inode *, int);
-extern void xfs_ichgtime_fast(struct xfs_inode *, struct inode *, int);
-
-#define xfs_vtoi(vp) \
-       ((struct xfs_inode *)vn_to_inode(vp)->i_private)
-
-#define XFS_I(inode) \
-       ((struct xfs_inode *)(inode)->i_private)
+extern void xfs_setup_inode(struct xfs_inode *);
 
 #endif /* __XFS_IOPS_H__ */
index 4d45d9351a6c7d0faef80065b73cc235714be712..cc0f7b3a97957687114dd961d9543cd5c807aeb3 100644 (file)
 #include <mrlock.h>
 #include <sv.h>
 #include <mutex.h>
-#include <sema.h>
 #include <time.h>
 
 #include <support/ktrace.h>
 #include <support/debug.h>
 #include <support/uuid.h>
 
+#include <linux/semaphore.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
 
 #define current_cpu()          (raw_smp_processor_id())
 #define current_pid()          (current->pid)
-#define current_fsuid(cred)    (current->fsuid)
-#define current_fsgid(cred)    (current->fsgid)
 #define current_test_flags(f)  (current->flags & (f))
 #define current_set_flags_nested(sp, f)                \
                (*(sp) = current->flags, current->flags |= (f))
 #define xfs_sort(a,n,s,fn)     sort(a,n,s,fn,NULL)
 #define xfs_stack_trace()      dump_stack()
 #define xfs_itruncate_data(ip, off)    \
-       (-vmtruncate(vn_to_inode(XFS_ITOV(ip)), (off)))
+       (-vmtruncate(VFS_I(ip), (off)))
 
 
 /* Move the kernel do_div definition off to one side */
index 82333b3e118e7d6491589c5ad524b179e4feec96..1957e5357d047b067b25719c34099bbb006a9cb6 100644 (file)
@@ -137,7 +137,7 @@ xfs_iozero(
        struct address_space    *mapping;
        int                     status;
 
-       mapping = ip->i_vnode->i_mapping;
+       mapping = VFS_I(ip)->i_mapping;
        do {
                unsigned offset, bytes;
                void *fsdata;
@@ -674,9 +674,7 @@ start:
         */
        if (likely(!(ioflags & IO_INVIS) &&
                   !mnt_want_write(file->f_path.mnt))) {
-               file_update_time(file);
-               xfs_ichgtime_fast(xip, inode,
-                                 XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+               xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
                mnt_drop_write(file->f_path.mnt);
        }
 
index 30ae96397e318854ab0eb93ecc124916e04bfde5..73c65f19e549f34dbf569cea7937b5971c44685e 100644 (file)
@@ -581,118 +581,6 @@ xfs_max_file_offset(
        return (((__uint64_t)pagefactor) << bitshift) - 1;
 }
 
-STATIC_INLINE void
-xfs_set_inodeops(
-       struct inode            *inode)
-{
-       switch (inode->i_mode & S_IFMT) {
-       case S_IFREG:
-               inode->i_op = &xfs_inode_operations;
-               inode->i_fop = &xfs_file_operations;
-               inode->i_mapping->a_ops = &xfs_address_space_operations;
-               break;
-       case S_IFDIR:
-               if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb))
-                       inode->i_op = &xfs_dir_ci_inode_operations;
-               else
-                       inode->i_op = &xfs_dir_inode_operations;
-               inode->i_fop = &xfs_dir_file_operations;
-               break;
-       case S_IFLNK:
-               inode->i_op = &xfs_symlink_inode_operations;
-               if (!(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE))
-                       inode->i_mapping->a_ops = &xfs_address_space_operations;
-               break;
-       default:
-               inode->i_op = &xfs_inode_operations;
-               init_special_inode(inode, inode->i_mode, inode->i_rdev);
-               break;
-       }
-}
-
-STATIC_INLINE void
-xfs_revalidate_inode(
-       xfs_mount_t             *mp,
-       bhv_vnode_t             *vp,
-       xfs_inode_t             *ip)
-{
-       struct inode            *inode = vn_to_inode(vp);
-
-       inode->i_mode   = ip->i_d.di_mode;
-       inode->i_nlink  = ip->i_d.di_nlink;
-       inode->i_uid    = ip->i_d.di_uid;
-       inode->i_gid    = ip->i_d.di_gid;
-
-       switch (inode->i_mode & S_IFMT) {
-       case S_IFBLK:
-       case S_IFCHR:
-               inode->i_rdev =
-                       MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff,
-                             sysv_minor(ip->i_df.if_u2.if_rdev));
-               break;
-       default:
-               inode->i_rdev = 0;
-               break;
-       }
-
-       inode->i_generation = ip->i_d.di_gen;
-       i_size_write(inode, ip->i_d.di_size);
-       inode->i_atime.tv_sec   = ip->i_d.di_atime.t_sec;
-       inode->i_atime.tv_nsec  = ip->i_d.di_atime.t_nsec;
-       inode->i_mtime.tv_sec   = ip->i_d.di_mtime.t_sec;
-       inode->i_mtime.tv_nsec  = ip->i_d.di_mtime.t_nsec;
-       inode->i_ctime.tv_sec   = ip->i_d.di_ctime.t_sec;
-       inode->i_ctime.tv_nsec  = ip->i_d.di_ctime.t_nsec;
-       if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE)
-               inode->i_flags |= S_IMMUTABLE;
-       else
-               inode->i_flags &= ~S_IMMUTABLE;
-       if (ip->i_d.di_flags & XFS_DIFLAG_APPEND)
-               inode->i_flags |= S_APPEND;
-       else
-               inode->i_flags &= ~S_APPEND;
-       if (ip->i_d.di_flags & XFS_DIFLAG_SYNC)
-               inode->i_flags |= S_SYNC;
-       else
-               inode->i_flags &= ~S_SYNC;
-       if (ip->i_d.di_flags & XFS_DIFLAG_NOATIME)
-               inode->i_flags |= S_NOATIME;
-       else
-               inode->i_flags &= ~S_NOATIME;
-       xfs_iflags_clear(ip, XFS_IMODIFIED);
-}
-
-void
-xfs_initialize_vnode(
-       struct xfs_mount        *mp,
-       bhv_vnode_t             *vp,
-       struct xfs_inode        *ip)
-{
-       struct inode            *inode = vn_to_inode(vp);
-
-       if (!ip->i_vnode) {
-               ip->i_vnode = vp;
-               inode->i_private = ip;
-       }
-
-       /*
-        * We need to set the ops vectors, and unlock the inode, but if
-        * we have been called during the new inode create process, it is
-        * too early to fill in the Linux inode.  We will get called a
-        * second time once the inode is properly set up, and then we can
-        * finish our work.
-        */
-       if (ip->i_d.di_mode != 0 && (inode->i_state & I_NEW)) {
-               xfs_revalidate_inode(mp, vp, ip);
-               xfs_set_inodeops(inode);
-
-               xfs_iflags_clear(ip, XFS_INEW);
-               barrier();
-
-               unlock_new_inode(inode);
-       }
-}
-
 int
 xfs_blkdev_get(
        xfs_mount_t             *mp,
@@ -982,26 +870,21 @@ STATIC struct inode *
 xfs_fs_alloc_inode(
        struct super_block      *sb)
 {
-       bhv_vnode_t             *vp;
-
-       vp = kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP);
-       if (unlikely(!vp))
-               return NULL;
-       return vn_to_inode(vp);
+       return kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP);
 }
 
 STATIC void
 xfs_fs_destroy_inode(
        struct inode            *inode)
 {
-       kmem_zone_free(xfs_vnode_zone, vn_from_inode(inode));
+       kmem_zone_free(xfs_vnode_zone, inode);
 }
 
 STATIC void
 xfs_fs_inode_init_once(
        void                    *vnode)
 {
-       inode_init_once(vn_to_inode((bhv_vnode_t *)vnode));
+       inode_init_once((struct inode *)vnode);
 }
 
 /*
@@ -1106,7 +989,7 @@ void
 xfs_flush_inode(
        xfs_inode_t     *ip)
 {
-       struct inode    *inode = ip->i_vnode;
+       struct inode    *inode = VFS_I(ip);
 
        igrab(inode);
        xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work);
@@ -1131,7 +1014,7 @@ void
 xfs_flush_device(
        xfs_inode_t     *ip)
 {
-       struct inode    *inode = vn_to_inode(XFS_ITOV(ip));
+       struct inode    *inode = VFS_I(ip);
 
        igrab(inode);
        xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work);
@@ -1200,6 +1083,15 @@ xfssyncd(
        return 0;
 }
 
+STATIC void
+xfs_free_fsname(
+       struct xfs_mount        *mp)
+{
+       kfree(mp->m_fsname);
+       kfree(mp->m_rtname);
+       kfree(mp->m_logname);
+}
+
 STATIC void
 xfs_fs_put_super(
        struct super_block      *sb)
@@ -1239,8 +1131,6 @@ xfs_fs_put_super(
        error = xfs_unmount_flush(mp, 0);
        WARN_ON(error);
 
-       IRELE(rip);
-
        /*
         * If we're forcing a shutdown, typically because of a media error,
         * we want to make sure we invalidate dirty pages that belong to
@@ -1257,10 +1147,12 @@ xfs_fs_put_super(
        }
 
        xfs_unmountfs(mp);
+       xfs_freesb(mp);
        xfs_icsb_destroy_counters(mp);
        xfs_close_devices(mp);
        xfs_qmops_put(mp);
        xfs_dmops_put(mp);
+       xfs_free_fsname(mp);
        kfree(mp);
 }
 
@@ -1517,6 +1409,8 @@ xfs_start_flags(
        struct xfs_mount_args   *ap,
        struct xfs_mount        *mp)
 {
+       int                     error;
+
        /* Values are in BBs */
        if ((ap->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
                /*
@@ -1549,17 +1443,27 @@ xfs_start_flags(
                        ap->logbufsize);
                return XFS_ERROR(EINVAL);
        }
+
+       error = ENOMEM;
+
        mp->m_logbsize = ap->logbufsize;
        mp->m_fsname_len = strlen(ap->fsname) + 1;
-       mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);
-       strcpy(mp->m_fsname, ap->fsname);
+
+       mp->m_fsname = kstrdup(ap->fsname, GFP_KERNEL);
+       if (!mp->m_fsname)
+               goto out;
+
        if (ap->rtname[0]) {
-               mp->m_rtname = kmem_alloc(strlen(ap->rtname) + 1, KM_SLEEP);
-               strcpy(mp->m_rtname, ap->rtname);
+               mp->m_rtname = kstrdup(ap->rtname, GFP_KERNEL);
+               if (!mp->m_rtname)
+                       goto out_free_fsname;
+
        }
+
        if (ap->logname[0]) {
-               mp->m_logname = kmem_alloc(strlen(ap->logname) + 1, KM_SLEEP);
-               strcpy(mp->m_logname, ap->logname);
+               mp->m_logname = kstrdup(ap->logname, GFP_KERNEL);
+               if (!mp->m_logname)
+                       goto out_free_rtname;
        }
 
        if (ap->flags & XFSMNT_WSYNC)
@@ -1632,6 +1536,14 @@ xfs_start_flags(
        if (ap->flags & XFSMNT_DMAPI)
                mp->m_flags |= XFS_MOUNT_DMAPI;
        return 0;
+
+
+ out_free_rtname:
+       kfree(mp->m_rtname);
+ out_free_fsname:
+       kfree(mp->m_fsname);
+ out:
+       return error;
 }
 
 /*
@@ -1792,10 +1704,10 @@ xfs_fs_fill_super(
         */
        error = xfs_start_flags(args, mp);
        if (error)
-               goto out_destroy_counters;
+               goto out_free_fsname;
        error = xfs_readsb(mp, flags);
        if (error)
-               goto out_destroy_counters;
+               goto out_free_fsname;
        error = xfs_finish_flags(args, mp);
        if (error)
                goto out_free_sb;
@@ -1811,7 +1723,7 @@ xfs_fs_fill_super(
        if (error)
                goto out_free_sb;
 
-       error = xfs_mountfs(mp, flags);
+       error = xfs_mountfs(mp);
        if (error)
                goto out_filestream_unmount;
 
@@ -1825,7 +1737,7 @@ xfs_fs_fill_super(
        sb->s_time_gran = 1;
        set_posix_acl_flag(sb);
 
-       root = igrab(mp->m_rootip->i_vnode);
+       root = igrab(VFS_I(mp->m_rootip));
        if (!root) {
                error = ENOENT;
                goto fail_unmount;
@@ -1857,7 +1769,8 @@ xfs_fs_fill_super(
        xfs_filestream_unmount(mp);
  out_free_sb:
        xfs_freesb(mp);
- out_destroy_counters:
+ out_free_fsname:
+       xfs_free_fsname(mp);
        xfs_icsb_destroy_counters(mp);
        xfs_close_devices(mp);
  out_put_qmops:
@@ -1890,10 +1803,8 @@ xfs_fs_fill_super(
        error = xfs_unmount_flush(mp, 0);
        WARN_ON(error);
 
-       IRELE(mp->m_rootip);
-
        xfs_unmountfs(mp);
-       goto out_destroy_counters;
+       goto out_free_sb;
 }
 
 STATIC int
@@ -2014,7 +1925,7 @@ xfs_free_trace_bufs(void)
 STATIC int __init
 xfs_init_zones(void)
 {
-       xfs_vnode_zone = kmem_zone_init_flags(sizeof(bhv_vnode_t), "xfs_vnode",
+       xfs_vnode_zone = kmem_zone_init_flags(sizeof(struct inode), "xfs_vnode",
                                        KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |
                                        KM_ZONE_SPREAD,
                                        xfs_fs_inode_init_once);
index b7d13da01bd6d45a0ce826511b1f0332e27dadff..fe2ef4e6a0f9e50fdb7a69ea8c60deb0e1892b7f 100644 (file)
@@ -101,9 +101,6 @@ struct block_device;
 
 extern __uint64_t xfs_max_file_offset(unsigned int);
 
-extern void xfs_initialize_vnode(struct xfs_mount *mp, bhv_vnode_t *vp,
-               struct xfs_inode *ip);
-
 extern void xfs_flush_inode(struct xfs_inode *);
 extern void xfs_flush_device(struct xfs_inode *);
 
index 25488b6d98817241e1bb99f6e7b5701701fc6538..b52528bbbfff7953510639c5fda9d447e995adee 100644 (file)
@@ -33,7 +33,7 @@
 
 
 /*
- * Dedicated vnode inactive/reclaim sync semaphores.
+ * Dedicated vnode inactive/reclaim sync wait queues.
  * Prime number of hash buckets since address is used as the key.
  */
 #define NVSYNC                  37
@@ -82,24 +82,6 @@ vn_ioerror(
                xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, f, l);
 }
 
-
-/*
- * Add a reference to a referenced vnode.
- */
-bhv_vnode_t *
-vn_hold(
-       bhv_vnode_t     *vp)
-{
-       struct inode    *inode;
-
-       XFS_STATS_INC(vn_hold);
-
-       inode = igrab(vn_to_inode(vp));
-       ASSERT(inode);
-
-       return vp;
-}
-
 #ifdef XFS_INODE_TRACE
 
 /*
@@ -108,7 +90,7 @@ vn_hold(
  */
 static inline int xfs_icount(struct xfs_inode *ip)
 {
-       bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
+       struct inode *vp = VFS_I(ip);
 
        if (vp)
                return vn_count(vp);
index 41ca2cec5d310da74c6b285c8cec9783e3b9e797..683ce16210ffefe8ee69dd54c3c85e46b29331ae 100644 (file)
@@ -22,20 +22,6 @@ struct file;
 struct xfs_iomap;
 struct attrlist_cursor_kern;
 
-typedef struct inode   bhv_vnode_t;
-
-/*
- * Vnode to Linux inode mapping.
- */
-static inline bhv_vnode_t *vn_from_inode(struct inode *inode)
-{
-       return inode;
-}
-static inline struct inode *vn_to_inode(bhv_vnode_t *vnode)
-{
-       return vnode;
-}
-
 /*
  * Return values for xfs_inactive.  A return value of
  * VN_INACTIVE_NOCACHE implies that the file system behavior
@@ -76,57 +62,52 @@ extern void vn_iowait(struct xfs_inode *ip);
 extern void    vn_iowake(struct xfs_inode *ip);
 extern void    vn_ioerror(struct xfs_inode *ip, int error, char *f, int l);
 
-static inline int vn_count(bhv_vnode_t *vp)
+static inline int vn_count(struct inode *vp)
 {
-       return atomic_read(&vn_to_inode(vp)->i_count);
+       return atomic_read(&vp->i_count);
 }
 
-/*
- * Vnode reference counting functions (and macros for compatibility).
- */
-extern bhv_vnode_t     *vn_hold(bhv_vnode_t *);
+#define IHOLD(ip) \
+do { \
+       ASSERT(atomic_read(&VFS_I(ip)->i_count) > 0) ; \
+       atomic_inc(&(VFS_I(ip)->i_count)); \
+       xfs_itrace_hold((ip), __FILE__, __LINE__, (inst_t *)__return_address); \
+} while (0)
 
-#if defined(XFS_INODE_TRACE)
-#define VN_HOLD(vp)            \
-       ((void)vn_hold(vp),     \
-         xfs_itrace_hold(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address))
-#define VN_RELE(vp)            \
-         (xfs_itrace_rele(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address), \
-          iput(vn_to_inode(vp)))
-#else
-#define VN_HOLD(vp)            ((void)vn_hold(vp))
-#define VN_RELE(vp)            (iput(vn_to_inode(vp)))
-#endif
+#define IRELE(ip) \
+do { \
+       xfs_itrace_rele((ip), __FILE__, __LINE__, (inst_t *)__return_address); \
+       iput(VFS_I(ip)); \
+} while (0)
 
-static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp)
+static inline struct inode *vn_grab(struct inode *vp)
 {
-       struct inode *inode = igrab(vn_to_inode(vp));
-       return inode ? vn_from_inode(inode) : NULL;
+       return igrab(vp);
 }
 
 /*
  * Dealing with bad inodes
  */
-static inline int VN_BAD(bhv_vnode_t *vp)
+static inline int VN_BAD(struct inode *vp)
 {
-       return is_bad_inode(vn_to_inode(vp));
+       return is_bad_inode(vp);
 }
 
 /*
  * Extracting atime values in various formats
  */
-static inline void vn_atime_to_bstime(bhv_vnode_t *vp, xfs_bstime_t *bs_atime)
+static inline void vn_atime_to_bstime(struct inode *vp, xfs_bstime_t *bs_atime)
 {
        bs_atime->tv_sec = vp->i_atime.tv_sec;
        bs_atime->tv_nsec = vp->i_atime.tv_nsec;
 }
 
-static inline void vn_atime_to_timespec(bhv_vnode_t *vp, struct timespec *ts)
+static inline void vn_atime_to_timespec(struct inode *vp, struct timespec *ts)
 {
        *ts = vp->i_atime;
 }
 
-static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt)
+static inline void vn_atime_to_time_t(struct inode *vp, time_t *tt)
 {
        *tt = vp->i_atime.tv_sec;
 }
@@ -134,9 +115,9 @@ static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt)
 /*
  * Some useful predicates.
  */
-#define VN_MAPPED(vp)  mapping_mapped(vn_to_inode(vp)->i_mapping)
-#define VN_CACHED(vp)  (vn_to_inode(vp)->i_mapping->nrpages)
-#define VN_DIRTY(vp)   mapping_tagged(vn_to_inode(vp)->i_mapping, \
+#define VN_MAPPED(vp)  mapping_mapped(vp->i_mapping)
+#define VN_CACHED(vp)  (vp->i_mapping->nrpages)
+#define VN_DIRTY(vp)   mapping_tagged(vp->i_mapping, \
                                        PAGECACHE_TAG_DIRTY)
 
 
index fc9f3fb39b7b31bfe7d0a778b69c4f7eb049eea7..f2705f2fd43c264674660da0285adb5e5a2c39db 100644 (file)
@@ -101,11 +101,18 @@ xfs_qm_dqinit(
        if (brandnewdquot) {
                dqp->dq_flnext = dqp->dq_flprev = dqp;
                mutex_init(&dqp->q_qlock);
-               initnsema(&dqp->q_flock, 1, "fdq");
                sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq");
 
+               /*
+                * Because we want to use a counting completion, complete
+                * the flush completion once to allow a single access to
+                * the flush completion without blocking.
+                */
+               init_completion(&dqp->q_flush);
+               complete(&dqp->q_flush);
+
 #ifdef XFS_DQUOT_TRACE
-               dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_SLEEP);
+               dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_NOFS);
                xfs_dqtrace_entry(dqp, "DQINIT");
 #endif
        } else {
@@ -150,7 +157,6 @@ xfs_qm_dqdestroy(
        ASSERT(! XFS_DQ_IS_ON_FREELIST(dqp));
 
        mutex_destroy(&dqp->q_qlock);
-       freesema(&dqp->q_flock);
        sv_destroy(&dqp->q_pinwait);
 
 #ifdef XFS_DQUOT_TRACE
@@ -431,7 +437,7 @@ xfs_qm_dqalloc(
         * when it unlocks the inode. Since we want to keep the quota
         * inode around, we bump the vnode ref count now.
         */
-       VN_HOLD(XFS_ITOV(quotip));
+       IHOLD(quotip);
 
        xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL);
        nmaps = 1;
@@ -1211,7 +1217,7 @@ xfs_qm_dqflush(
        int                     error;
 
        ASSERT(XFS_DQ_IS_LOCKED(dqp));
-       ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp));
+       ASSERT(!completion_done(&dqp->q_flush));
        xfs_dqtrace_entry(dqp, "DQFLUSH");
 
        /*
@@ -1348,34 +1354,18 @@ xfs_qm_dqflush_done(
        xfs_dqfunlock(dqp);
 }
 
-
-int
-xfs_qm_dqflock_nowait(
-       xfs_dquot_t *dqp)
-{
-       int locked;
-
-       locked = cpsema(&((dqp)->q_flock));
-
-       /* XXX ifdef these out */
-       if (locked)
-               (dqp)->dq_flags |= XFS_DQ_FLOCKED;
-       return (locked);
-}
-
-
 int
 xfs_qm_dqlock_nowait(
        xfs_dquot_t *dqp)
 {
-       return (mutex_trylock(&((dqp)->q_qlock)));
+       return mutex_trylock(&dqp->q_qlock);
 }
 
 void
 xfs_dqlock(
        xfs_dquot_t *dqp)
 {
-       mutex_lock(&(dqp->q_qlock));
+       mutex_lock(&dqp->q_qlock);
 }
 
 void
@@ -1468,7 +1458,7 @@ xfs_qm_dqpurge(
         * if we're turning off quotas. Basically, we need this flush
         * lock, and are willing to block on it.
         */
-       if (! xfs_qm_dqflock_nowait(dqp)) {
+       if (!xfs_dqflock_nowait(dqp)) {
                /*
                 * Block on the flush lock after nudging dquot buffer,
                 * if it is incore.
index f7393bba4e95b38a6d9ec7ee0890633f64227e1f..8958d0faf8d37606c806a1ce22d9c996036bdf08 100644 (file)
@@ -82,7 +82,7 @@ typedef struct xfs_dquot {
        xfs_qcnt_t       q_res_icount;  /* total inos allocd+reserved */
        xfs_qcnt_t       q_res_rtbcount;/* total realtime blks used+reserved */
        mutex_t          q_qlock;       /* quota lock */
-       sema_t           q_flock;       /* flush lock */
+       struct completion q_flush;      /* flush completion queue */
        uint             q_pincount;    /* pin count for this dquot */
        sv_t             q_pinwait;     /* sync var for pinning */
 #ifdef XFS_DQUOT_TRACE
@@ -113,17 +113,25 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
 
 
 /*
- * The following three routines simply manage the q_flock
- * semaphore embedded in the dquot.  This semaphore synchronizes
- * processes attempting to flush the in-core dquot back to disk.
+ * Manage the q_flush completion queue embedded in the dquot.  This completion
+ * queue synchronizes processes attempting to flush the in-core dquot back to
+ * disk.
  */
-#define xfs_dqflock(dqp)        { psema(&((dqp)->q_flock), PINOD | PRECALC);\
-                                  (dqp)->dq_flags |= XFS_DQ_FLOCKED; }
-#define xfs_dqfunlock(dqp)      { ASSERT(issemalocked(&((dqp)->q_flock))); \
-                                  vsema(&((dqp)->q_flock)); \
-                                  (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); }
+static inline void xfs_dqflock(xfs_dquot_t *dqp)
+{
+       wait_for_completion(&dqp->q_flush);
+}
+
+static inline int xfs_dqflock_nowait(xfs_dquot_t *dqp)
+{
+       return try_wait_for_completion(&dqp->q_flush);
+}
+
+static inline void xfs_dqfunlock(xfs_dquot_t *dqp)
+{
+       complete(&dqp->q_flush);
+}
 
-#define XFS_DQ_IS_FLUSH_LOCKED(dqp) (issemalocked(&((dqp)->q_flock)))
 #define XFS_DQ_IS_ON_FREELIST(dqp)  ((dqp)->dq_flnext != (dqp))
 #define XFS_DQ_IS_DIRTY(dqp)   ((dqp)->dq_flags & XFS_DQ_DIRTY)
 #define XFS_QM_ISUDQ(dqp)      ((dqp)->dq_flags & XFS_DQ_USER)
@@ -167,7 +175,6 @@ extern int          xfs_qm_dqflush(xfs_dquot_t *, uint);
 extern int             xfs_qm_dqpurge(xfs_dquot_t *);
 extern void            xfs_qm_dqunpin_wait(xfs_dquot_t *);
 extern int             xfs_qm_dqlock_nowait(xfs_dquot_t *);
-extern int             xfs_qm_dqflock_nowait(xfs_dquot_t *);
 extern void            xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp);
 extern void            xfs_qm_adjust_dqtimers(xfs_mount_t *,
                                        xfs_disk_dquot_t *);
index 08d2fc89e6a1741fc24d156f0ce96ea1e5c0780f..f028644caa5eb090e93620aae600bd6d9d87d26d 100644 (file)
@@ -151,7 +151,7 @@ xfs_qm_dquot_logitem_push(
        dqp = logitem->qli_dquot;
 
        ASSERT(XFS_DQ_IS_LOCKED(dqp));
-       ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp));
+       ASSERT(!completion_done(&dqp->q_flush));
 
        /*
         * Since we were able to lock the dquot's flush lock and
@@ -245,7 +245,7 @@ xfs_qm_dquot_logitem_pushbuf(
         * inode flush completed and the inode was taken off the AIL.
         * So, just get out.
         */
-       if (!issemalocked(&(dqp->q_flock))  ||
+       if (completion_done(&dqp->q_flush)  ||
            ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) {
                qip->qli_pushbuf_flag = 0;
                xfs_dqunlock(dqp);
@@ -258,7 +258,7 @@ xfs_qm_dquot_logitem_pushbuf(
        if (bp != NULL) {
                if (XFS_BUF_ISDELAYWRITE(bp)) {
                        dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) &&
-                                 issemalocked(&(dqp->q_flock)));
+                                 !completion_done(&dqp->q_flush));
                        qip->qli_pushbuf_flag = 0;
                        xfs_dqunlock(dqp);
 
@@ -317,7 +317,7 @@ xfs_qm_dquot_logitem_trylock(
                return (XFS_ITEM_LOCKED);
 
        retval = XFS_ITEM_SUCCESS;
-       if (! xfs_qm_dqflock_nowait(dqp)) {
+       if (!xfs_dqflock_nowait(dqp)) {
                /*
                 * The dquot is already being flushed.  It may have been
                 * flushed delayed write, however, and we don't want to
index 021934a3d45661149a1301303a9f8e53cc244713..df0ffef9775ae75d54c647a7b56c4ba248028a01 100644 (file)
@@ -310,8 +310,7 @@ xfs_qm_unmount_quotadestroy(
  */
 void
 xfs_qm_mount_quotas(
-       xfs_mount_t     *mp,
-       int             mfsi_flags)
+       xfs_mount_t     *mp)
 {
        int             error = 0;
        uint            sbf;
@@ -346,8 +345,7 @@ xfs_qm_mount_quotas(
        /*
         * If any of the quotas are not consistent, do a quotacheck.
         */
-       if (XFS_QM_NEED_QUOTACHECK(mp) &&
-           !(mfsi_flags & XFS_MFSI_NO_QUOTACHECK)) {
+       if (XFS_QM_NEED_QUOTACHECK(mp)) {
                error = xfs_qm_quotacheck(mp);
                if (error) {
                        /* Quotacheck failed and disabled quotas. */
@@ -484,7 +482,7 @@ again:
                xfs_dqtrace_entry(dqp, "FLUSHALL: DQDIRTY");
                /* XXX a sentinel would be better */
                recl = XFS_QI_MPLRECLAIMS(mp);
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        /*
                         * If we can't grab the flush lock then check
                         * to see if the dquot has been flushed delayed
@@ -1062,7 +1060,7 @@ xfs_qm_sync(
 
                /* XXX a sentinel would be better */
                recl = XFS_QI_MPLRECLAIMS(mp);
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        if (nowait) {
                                xfs_dqunlock(dqp);
                                continue;
@@ -2079,7 +2077,7 @@ xfs_qm_shake_freelist(
                 * Try to grab the flush lock. If this dquot is in the process of
                 * getting flushed to disk, we don't want to reclaim it.
                 */
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        xfs_dqunlock(dqp);
                        dqp = dqp->dq_flnext;
                        continue;
@@ -2257,7 +2255,7 @@ xfs_qm_dqreclaim_one(void)
                 * Try to grab the flush lock. If this dquot is in the process of
                 * getting flushed to disk, we don't want to reclaim it.
                 */
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        xfs_dqunlock(dqp);
                        continue;
                }
index cd2300e374afeaffbf49949c97450f1c3bf93700..44f25349e478bb7eb7db859da7c49c24c0cf75d1 100644 (file)
@@ -165,7 +165,7 @@ typedef struct xfs_dquot_acct {
 #define XFS_QM_RELE(xqm)       ((xqm)->qm_nrefs--)
 
 extern void            xfs_qm_destroy_quotainfo(xfs_mount_t *);
-extern void            xfs_qm_mount_quotas(xfs_mount_t *, int);
+extern void            xfs_qm_mount_quotas(xfs_mount_t *);
 extern int             xfs_qm_quotacheck(xfs_mount_t *);
 extern void            xfs_qm_unmount_quotadestroy(xfs_mount_t *);
 extern int             xfs_qm_unmount_quotas(xfs_mount_t *);
index f4f6c4c861d79df6f7f0a20c4ddc5ce09ef43485..eea2e60b456b6e962bd30872383e9ce07a0bfe31 100644 (file)
@@ -162,7 +162,7 @@ xfs_qm_newmount(
                         * mounting, and get on with the boring life
                         * without disk quotas.
                         */
-                       xfs_qm_mount_quotas(mp, 0);
+                       xfs_qm_mount_quotas(mp);
                } else {
                        /*
                         * Clear the quota flags, but remember them. This
@@ -184,13 +184,12 @@ STATIC int
 xfs_qm_endmount(
        xfs_mount_t     *mp,
        uint            needquotamount,
-       uint            quotaflags,
-       int             mfsi_flags)
+       uint            quotaflags)
 {
        if (needquotamount) {
                ASSERT(mp->m_qflags == 0);
                mp->m_qflags = quotaflags;
-               xfs_qm_mount_quotas(mp, mfsi_flags);
+               xfs_qm_mount_quotas(mp);
        }
 
 #if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
index adfb8723f65af336d92501163aff0ee095634828..1a3b803dfa55fbd2ca671e589e60098f6f5a0194 100644 (file)
@@ -1034,7 +1034,7 @@ xfs_qm_dqrele_all_inodes(
 {
        xfs_inode_t     *ip, *topino;
        uint            ireclaims;
-       bhv_vnode_t     *vp;
+       struct inode    *vp;
        boolean_t       vnode_refd;
 
        ASSERT(mp->m_quotainfo);
@@ -1059,7 +1059,7 @@ again:
                        ip = ip->i_mnext;
                        continue;
                }
-               vp = XFS_ITOV_NULL(ip);
+               vp = VFS_I(ip);
                if (!vp) {
                        ASSERT(ip->i_udquot == NULL);
                        ASSERT(ip->i_gdquot == NULL);
index 3e4648ad9cfcbda429ed52587d42a1d989fb21f5..b2f639a1416f0ecd1c0b91e4958584de823c3a46 100644 (file)
 #include <linux/capability.h>
 #include <linux/posix_acl_xattr.h>
 
-STATIC int     xfs_acl_setmode(bhv_vnode_t *, xfs_acl_t *, int *);
+STATIC int     xfs_acl_setmode(struct inode *, xfs_acl_t *, int *);
 STATIC void     xfs_acl_filter_mode(mode_t, xfs_acl_t *);
 STATIC void    xfs_acl_get_endian(xfs_acl_t *);
 STATIC int     xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *);
 STATIC int     xfs_acl_invalid(xfs_acl_t *);
 STATIC void    xfs_acl_sync_mode(mode_t, xfs_acl_t *);
-STATIC void    xfs_acl_get_attr(bhv_vnode_t *, xfs_acl_t *, int, int, int *);
-STATIC void    xfs_acl_set_attr(bhv_vnode_t *, xfs_acl_t *, int, int *);
-STATIC int     xfs_acl_allow_set(bhv_vnode_t *, int);
+STATIC void    xfs_acl_get_attr(struct inode *, xfs_acl_t *, int, int, int *);
+STATIC void    xfs_acl_set_attr(struct inode *, xfs_acl_t *, int, int *);
+STATIC int     xfs_acl_allow_set(struct inode *, int);
 
 kmem_zone_t *xfs_acl_zone;
 
@@ -55,7 +55,7 @@ kmem_zone_t *xfs_acl_zone;
  */
 int
 xfs_acl_vhasacl_access(
-       bhv_vnode_t     *vp)
+       struct inode    *vp)
 {
        int             error;
 
@@ -68,7 +68,7 @@ xfs_acl_vhasacl_access(
  */
 int
 xfs_acl_vhasacl_default(
-       bhv_vnode_t     *vp)
+       struct inode    *vp)
 {
        int             error;
 
@@ -207,7 +207,7 @@ posix_acl_xfs_to_xattr(
 
 int
 xfs_acl_vget(
-       bhv_vnode_t     *vp,
+       struct inode    *vp,
        void            *acl,
        size_t          size,
        int             kind)
@@ -217,7 +217,6 @@ xfs_acl_vget(
        posix_acl_xattr_header  *ext_acl = acl;
        int                     flags = 0;
 
-       VN_HOLD(vp);
        if(size) {
                if (!(_ACL_ALLOC(xfs_acl))) {
                        error = ENOMEM;
@@ -239,11 +238,10 @@ xfs_acl_vget(
                        goto out;
                }
                if (kind == _ACL_TYPE_ACCESS)
-                       xfs_acl_sync_mode(xfs_vtoi(vp)->i_d.di_mode, xfs_acl);
+                       xfs_acl_sync_mode(XFS_I(vp)->i_d.di_mode, xfs_acl);
                error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size);
        }
 out:
-       VN_RELE(vp);
        if(xfs_acl)
                _ACL_FREE(xfs_acl);
        return -error;
@@ -251,28 +249,26 @@ out:
 
 int
 xfs_acl_vremove(
-       bhv_vnode_t     *vp,
+       struct inode    *vp,
        int             kind)
 {
        int             error;
 
-       VN_HOLD(vp);
        error = xfs_acl_allow_set(vp, kind);
        if (!error) {
-               error = xfs_attr_remove(xfs_vtoi(vp),
+               error = xfs_attr_remove(XFS_I(vp),
                                                kind == _ACL_TYPE_DEFAULT?
                                                SGI_ACL_DEFAULT: SGI_ACL_FILE,
                                                ATTR_ROOT);
                if (error == ENOATTR)
                        error = 0;      /* 'scool */
        }
-       VN_RELE(vp);
        return -error;
 }
 
 int
 xfs_acl_vset(
-       bhv_vnode_t             *vp,
+       struct inode            *vp,
        void                    *acl,
        size_t                  size,
        int                     kind)
@@ -298,7 +294,6 @@ xfs_acl_vset(
                return 0;
        }
 
-       VN_HOLD(vp);
        error = xfs_acl_allow_set(vp, kind);
 
        /* Incoming ACL exists, set file mode based on its value */
@@ -321,7 +316,6 @@ xfs_acl_vset(
        }
 
 out:
-       VN_RELE(vp);
        _ACL_FREE(xfs_acl);
        return -error;
 }
@@ -363,7 +357,7 @@ xfs_acl_iaccess(
 
 STATIC int
 xfs_acl_allow_set(
-       bhv_vnode_t     *vp,
+       struct inode    *vp,
        int             kind)
 {
        if (vp->i_flags & (S_IMMUTABLE|S_APPEND))
@@ -372,7 +366,7 @@ xfs_acl_allow_set(
                return ENOTDIR;
        if (vp->i_sb->s_flags & MS_RDONLY)
                return EROFS;
-       if (xfs_vtoi(vp)->i_d.di_uid != current->fsuid && !capable(CAP_FOWNER))
+       if (XFS_I(vp)->i_d.di_uid != current->fsuid && !capable(CAP_FOWNER))
                return EPERM;
        return 0;
 }
@@ -566,7 +560,7 @@ xfs_acl_get_endian(
  */
 STATIC void
 xfs_acl_get_attr(
-       bhv_vnode_t     *vp,
+       struct inode    *vp,
        xfs_acl_t       *aclp,
        int             kind,
        int             flags,
@@ -576,7 +570,7 @@ xfs_acl_get_attr(
 
        ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1);
        flags |= ATTR_ROOT;
-       *error = xfs_attr_get(xfs_vtoi(vp),
+       *error = xfs_attr_get(XFS_I(vp),
                                        kind == _ACL_TYPE_ACCESS ?
                                        SGI_ACL_FILE : SGI_ACL_DEFAULT,
                                        (char *)aclp, &len, flags);
@@ -590,7 +584,7 @@ xfs_acl_get_attr(
  */
 STATIC void
 xfs_acl_set_attr(
-       bhv_vnode_t     *vp,
+       struct inode    *vp,
        xfs_acl_t       *aclp,
        int             kind,
        int             *error)
@@ -615,7 +609,7 @@ xfs_acl_set_attr(
                INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
        }
        INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
-       *error = xfs_attr_set(xfs_vtoi(vp),
+       *error = xfs_attr_set(XFS_I(vp),
                                kind == _ACL_TYPE_ACCESS ?
                                SGI_ACL_FILE: SGI_ACL_DEFAULT,
                                (char *)newacl, len, ATTR_ROOT);
@@ -624,7 +618,7 @@ xfs_acl_set_attr(
 
 int
 xfs_acl_vtoacl(
-       bhv_vnode_t     *vp,
+       struct inode    *vp,
        xfs_acl_t       *access_acl,
        xfs_acl_t       *default_acl)
 {
@@ -639,7 +633,7 @@ xfs_acl_vtoacl(
                if (error)
                        access_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
                else /* We have a good ACL and the file mode, synchronize. */
-                       xfs_acl_sync_mode(xfs_vtoi(vp)->i_d.di_mode, access_acl);
+                       xfs_acl_sync_mode(XFS_I(vp)->i_d.di_mode, access_acl);
        }
 
        if (default_acl) {
@@ -656,7 +650,7 @@ xfs_acl_vtoacl(
  */
 int
 xfs_acl_inherit(
-       bhv_vnode_t     *vp,
+       struct inode    *vp,
        mode_t          mode,
        xfs_acl_t       *pdaclp)
 {
@@ -715,7 +709,7 @@ out_error:
  */
 STATIC int
 xfs_acl_setmode(
-       bhv_vnode_t     *vp,
+       struct inode    *vp,
        xfs_acl_t       *acl,
        int             *basicperms)
 {
@@ -734,7 +728,7 @@ xfs_acl_setmode(
         * mode.  The m:: bits take precedence over the g:: bits.
         */
        iattr.ia_valid = ATTR_MODE;
-       iattr.ia_mode = xfs_vtoi(vp)->i_d.di_mode;
+       iattr.ia_mode = XFS_I(vp)->i_d.di_mode;
        iattr.ia_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
        ap = acl->acl_entry;
        for (i = 0; i < acl->acl_cnt; ++i) {
@@ -764,7 +758,7 @@ xfs_acl_setmode(
        if (gap && nomask)
                iattr.ia_mode |= gap->ae_perm << 3;
 
-       return xfs_setattr(xfs_vtoi(vp), &iattr, 0, sys_cred);
+       return xfs_setattr(XFS_I(vp), &iattr, 0, sys_cred);
 }
 
 /*
index 323ee94cf831cfbba001e890edfeecbb18bf69a4..a4e293b93efaa02bca467142357d17e59e60290a 100644 (file)
@@ -59,14 +59,14 @@ extern struct kmem_zone *xfs_acl_zone;
                (zone) = kmem_zone_init(sizeof(xfs_acl_t), (name))
 #define xfs_acl_zone_destroy(zone)     kmem_zone_destroy(zone)
 
-extern int xfs_acl_inherit(bhv_vnode_t *, mode_t mode, xfs_acl_t *);
+extern int xfs_acl_inherit(struct inode *, mode_t mode, xfs_acl_t *);
 extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *);
-extern int xfs_acl_vtoacl(bhv_vnode_t *, xfs_acl_t *, xfs_acl_t *);
-extern int xfs_acl_vhasacl_access(bhv_vnode_t *);
-extern int xfs_acl_vhasacl_default(bhv_vnode_t *);
-extern int xfs_acl_vset(bhv_vnode_t *, void *, size_t, int);
-extern int xfs_acl_vget(bhv_vnode_t *, void *, size_t, int);
-extern int xfs_acl_vremove(bhv_vnode_t *, int);
+extern int xfs_acl_vtoacl(struct inode *, xfs_acl_t *, xfs_acl_t *);
+extern int xfs_acl_vhasacl_access(struct inode *);
+extern int xfs_acl_vhasacl_default(struct inode *);
+extern int xfs_acl_vset(struct inode *, void *, size_t, int);
+extern int xfs_acl_vget(struct inode *, void *, size_t, int);
+extern int xfs_acl_vremove(struct inode *, int);
 
 #define _ACL_PERM_INVALID(perm)        ((perm) & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
 
index f9472a2076d4ec4a100d3e154ec3abada620844c..0b3b5efe848cbbf883373a971cf5b34d1c9951e7 100644 (file)
        ((__u8*)(pointer))[1] = (((value)     ) & 0xff); \
     }
 
-/* define generic INT_ macros */
-
-#define INT_GET(reference,arch) \
-    (((arch) == ARCH_NOCONVERT) \
-       ? \
-           (reference) \
-       : \
-           INT_SWAP((reference),(reference)) \
-    )
-
 /* does not return a value */
 #define INT_SET(reference,arch,valueref) \
     (__builtin_constant_p(valueref) ? \
        ) \
     )
 
-/* does not return a value */
-#define INT_MOD_EXPR(reference,arch,code) \
-    (((arch) == ARCH_NOCONVERT) \
-       ? \
-           (void)((reference) code) \
-       : \
-           (void)( \
-               (reference) = INT_GET((reference),arch) , \
-               ((reference) code), \
-               INT_SET(reference, arch, reference) \
-           ) \
-    )
-
-/* does not return a value */
-#define INT_MOD(reference,arch,delta) \
-    (void)( \
-       INT_MOD_EXPR(reference,arch,+=(delta)) \
-    )
-
-/*
- * INT_COPY - copy a value between two locations with the
- *           _same architecture_ but _potentially different sizes_
- *
- *         if the types of the two parameters are equal or they are
- *             in native architecture, a simple copy is done
- *
- *         otherwise, architecture conversions are done
- *
- */
-
-/* does not return a value */
-#define INT_COPY(dst,src,arch) \
-    ( \
-       ((sizeof(dst) == sizeof(src)) || ((arch) == ARCH_NOCONVERT)) \
-           ? \
-               (void)((dst) = (src)) \
-           : \
-               INT_SET(dst, arch, INT_GET(src, arch)) \
-    )
-
-/*
- * INT_XLATE - copy a value in either direction between two locations
- *            with different architectures
- *
- *                 dir < 0     - copy from memory to buffer (native to arch)
- *                 dir > 0     - copy from buffer to memory (arch to native)
- */
-
-/* does not return a value */
-#define INT_XLATE(buf,mem,dir,arch) {\
-    ASSERT(dir); \
-    if (dir>0) { \
-       (mem)=INT_GET(buf, arch); \
-    } else { \
-       INT_SET(buf, arch, mem); \
-    } \
-}
-
 /*
  * In directories inode numbers are stored as unaligned arrays of unsigned
  * 8bit integers on disk.
index 78de80e3caa2f4bfdee2704a88e3637fc388894f..f7cdc28aff413bb8b5d2fa866157a2e27c80cdcb 100644 (file)
@@ -194,6 +194,46 @@ xfs_attr_get(
        return(error);
 }
 
+/*
+ * Calculate how many blocks we need for the new attribute,
+ */
+int
+xfs_attr_calc_size(
+       struct xfs_inode        *ip,
+       int                     namelen,
+       int                     valuelen,
+       int                     *local)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       int                     size;
+       int                     nblks;
+
+       /*
+        * Determine space new attribute will use, and if it would be
+        * "local" or "remote" (note: local != inline).
+        */
+       size = xfs_attr_leaf_newentsize(namelen, valuelen,
+                                       mp->m_sb.sb_blocksize, local);
+
+       nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
+       if (*local) {
+               if (size > (mp->m_sb.sb_blocksize >> 1)) {
+                       /* Double split possible */
+                       nblks *= 2;
+               }
+       } else {
+               /*
+                * Out of line attribute, cannot double split, but
+                * make room for the attribute value itself.
+                */
+               uint    dblocks = XFS_B_TO_FSB(mp, valuelen);
+               nblks += dblocks;
+               nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
+       }
+
+       return nblks;
+}
+
 STATIC int
 xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
                char *value, int valuelen, int flags)
@@ -202,10 +242,9 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
        xfs_fsblock_t   firstblock;
        xfs_bmap_free_t flist;
        int             error, err2, committed;
-       int             local, size;
-       uint            nblks;
        xfs_mount_t     *mp = dp->i_mount;
        int             rsvd = (flags & ATTR_ROOT) != 0;
+       int             local;
 
        /*
         * Attach the dquots to the inode.
@@ -241,30 +280,8 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
        args.whichfork = XFS_ATTR_FORK;
        args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
 
-       /*
-        * Determine space new attribute will use, and if it would be
-        * "local" or "remote" (note: local != inline).
-        */
-       size = xfs_attr_leaf_newentsize(name->len, valuelen,
-                                       mp->m_sb.sb_blocksize, &local);
-
-       nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
-       if (local) {
-               if (size > (mp->m_sb.sb_blocksize >> 1)) {
-                       /* Double split possible */
-                       nblks <<= 1;
-               }
-       } else {
-               uint    dblocks = XFS_B_TO_FSB(mp, valuelen);
-               /* Out of line attribute, cannot double split, but make
-                * room for the attribute value itself.
-                */
-               nblks += dblocks;
-               nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
-       }
-
        /* Size is now blocks for attribute data */
-       args.total = nblks;
+       args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local);
 
        /*
         * Start our first transaction of the day.
@@ -286,18 +303,17 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
        if (rsvd)
                args.trans->t_flags |= XFS_TRANS_RESERVE;
 
-       if ((error = xfs_trans_reserve(args.trans, (uint) nblks,
-                                     XFS_ATTRSET_LOG_RES(mp, nblks),
-                                     0, XFS_TRANS_PERM_LOG_RES,
-                                     XFS_ATTRSET_LOG_COUNT))) {
+       if ((error = xfs_trans_reserve(args.trans, args.total,
+                       XFS_ATTRSET_LOG_RES(mp, args.total), 0,
+                       XFS_TRANS_PERM_LOG_RES, XFS_ATTRSET_LOG_COUNT))) {
                xfs_trans_cancel(args.trans, 0);
                return(error);
        }
        xfs_ilock(dp, XFS_ILOCK_EXCL);
 
-       error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, nblks, 0,
-                        rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
-                               XFS_QMOPT_RES_REGBLKS);
+       error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, args.total, 0,
+                               rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
+                                      XFS_QMOPT_RES_REGBLKS);
        if (error) {
                xfs_iunlock(dp, XFS_ILOCK_EXCL);
                xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES);
@@ -384,7 +400,9 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
                 * Commit the leaf transformation.  We'll need another (linked)
                 * transaction to add the new attribute to the leaf.
                 */
-               if ((error = xfs_attr_rolltrans(&args.trans, dp)))
+
+               error = xfs_trans_roll(&args.trans, dp);
+               if (error)
                        goto out;
 
        }
@@ -964,7 +982,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                 * Commit the current trans (including the inode) and start
                 * a new one.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        return (error);
 
                /*
@@ -978,7 +997,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
         * Commit the transaction that added the attr name so that
         * later routines can manage their own transactions.
         */
-       if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+       error = xfs_trans_roll(&args->trans, dp);
+       if (error)
                return (error);
 
        /*
@@ -1067,7 +1087,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                /*
                 * Commit the remove and start the next trans in series.
                 */
-               error = xfs_attr_rolltrans(&args->trans, dp);
+               error = xfs_trans_roll(&args->trans, dp);
 
        } else if (args->rmtblkno > 0) {
                /*
@@ -1298,7 +1318,8 @@ restart:
                         * Commit the node conversion and start the next
                         * trans in the chain.
                         */
-                       if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+                       error = xfs_trans_roll(&args->trans, dp);
+                       if (error)
                                goto out;
 
                        goto restart;
@@ -1349,7 +1370,8 @@ restart:
         * Commit the leaf addition or btree split and start the next
         * trans in the chain.
         */
-       if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+       error = xfs_trans_roll(&args->trans, dp);
+       if (error)
                goto out;
 
        /*
@@ -1449,7 +1471,8 @@ restart:
                /*
                 * Commit and start the next trans in the chain.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        goto out;
 
        } else if (args->rmtblkno > 0) {
@@ -1581,7 +1604,8 @@ xfs_attr_node_removename(xfs_da_args_t *args)
                /*
                 * Commit the Btree join operation and start a new trans.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        goto out;
        }
 
@@ -2082,7 +2106,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
                /*
                 * Start the next trans in the chain.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        return (error);
        }
 
@@ -2232,7 +2257,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
                /*
                 * Close out trans and start the next one in the chain.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, args->dp)))
+               error = xfs_trans_roll(&args->trans, args->dp);
+               if (error)
                        return (error);
        }
        return(0);
index 8b2d31c19e4dbd3b2abb6ccb8bb9921d2a447ff4..fb3b2a68b9b9d4fc6fc86956cf07c5c62611190b 100644 (file)
@@ -129,6 +129,7 @@ typedef struct xfs_attr_list_context {
 /*
  * Overall external interface routines.
  */
+int xfs_attr_calc_size(struct xfs_inode *, int, int, int *);
 int xfs_attr_inactive(struct xfs_inode *dp);
 int xfs_attr_fetch(struct xfs_inode *, struct xfs_name *, char *, int *, int);
 int xfs_attr_rmtval_get(struct xfs_da_args *args);
index 23ef5d7c87e1ba774709594da87cae681a2033ae..79da6b2ea99efa35dee2f72f12785598995daf5a 100644 (file)
@@ -2498,9 +2498,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args)
        /*
         * Commit the flag value change and start the next trans in series.
         */
-       error = xfs_attr_rolltrans(&args->trans, args->dp);
-
-       return(error);
+       return xfs_trans_roll(&args->trans, args->dp);
 }
 
 /*
@@ -2547,9 +2545,7 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args)
        /*
         * Commit the flag value change and start the next trans in series.
         */
-       error = xfs_attr_rolltrans(&args->trans, args->dp);
-
-       return(error);
+       return xfs_trans_roll(&args->trans, args->dp);
 }
 
 /*
@@ -2665,7 +2661,7 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args)
        /*
         * Commit the flag value change and start the next trans in series.
         */
-       error = xfs_attr_rolltrans(&args->trans, args->dp);
+       error = xfs_trans_roll(&args->trans, args->dp);
 
        return(error);
 }
@@ -2723,7 +2719,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
        /*
         * Commit the invalidate and start the next transaction.
         */
-       error = xfs_attr_rolltrans(trans, dp);
+       error = xfs_trans_roll(trans, dp);
 
        return (error);
 }
@@ -2825,7 +2821,8 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
                /*
                 * Atomically commit the whole invalidate stuff.
                 */
-               if ((error = xfs_attr_rolltrans(trans, dp)))
+               error = xfs_trans_roll(trans, dp);
+               if (error)
                        return (error);
        }
 
@@ -2964,7 +2961,8 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
                        /*
                         * Roll to next transaction.
                         */
-                       if ((error = xfs_attr_rolltrans(trans, dp)))
+                       error = xfs_trans_roll(trans, dp);
+                       if (error)
                                return (error);
                }
 
@@ -2974,60 +2972,3 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
 
        return(0);
 }
-
-
-/*
- * Roll from one trans in the sequence of PERMANENT transactions to the next.
- */
-int
-xfs_attr_rolltrans(xfs_trans_t **transp, xfs_inode_t *dp)
-{
-       xfs_trans_t *trans;
-       unsigned int logres, count;
-       int     error;
-
-       /*
-        * Ensure that the inode is always logged.
-        */
-       trans = *transp;
-       xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
-
-       /*
-        * Copy the critical parameters from one trans to the next.
-        */
-       logres = trans->t_log_res;
-       count = trans->t_log_count;
-       *transp = xfs_trans_dup(trans);
-
-       /*
-        * Commit the current transaction.
-        * If this commit failed, then it'd just unlock those items that
-        * are not marked ihold. That also means that a filesystem shutdown
-        * is in progress. The caller takes the responsibility to cancel
-        * the duplicate transaction that gets returned.
-        */
-       if ((error = xfs_trans_commit(trans, 0)))
-               return (error);
-
-       trans = *transp;
-
-       /*
-        * Reserve space in the log for th next transaction.
-        * This also pushes items in the "AIL", the list of logged items,
-        * out to disk if they are taking up space at the tail of the log
-        * that we want to use.  This requires that either nothing be locked
-        * across this call, or that anything that is locked be logged in
-        * the prior and the next transactions.
-        */
-       error = xfs_trans_reserve(trans, 0, logres, 0,
-                                 XFS_TRANS_PERM_LOG_RES, count);
-       /*
-        *  Ensure that the inode is in the new transaction and locked.
-        */
-       if (!error) {
-               xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL);
-               xfs_trans_ihold(trans, dp);
-       }
-       return (error);
-
-}
index 5ecf437b782556ffc663f55f9eac51fa4f9291c3..83e9af417ca21280492fcfa37a7fd93494429fbb 100644 (file)
@@ -274,6 +274,4 @@ int xfs_attr_leaf_order(struct xfs_dabuf *leaf1_bp,
                                   struct xfs_dabuf *leaf2_bp);
 int    xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize,
                                        int *local);
-int    xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp);
-
 #endif /* __XFS_ATTR_LEAF_H__ */
index fab0b6d5a41be3916ac8893a2f82f142cd4443f4..48228848f5ae3e2e6f52900b6d0ea7215274a36d 100644 (file)
  * XFS bit manipulation routines, used in non-realtime code.
  */
 
-#ifndef HAVE_ARCH_HIGHBIT
-/*
- * Index of high bit number in byte, -1 for none set, 0..7 otherwise.
- */
-static const char xfs_highbit[256] = {
-       -1, 0, 1, 1, 2, 2, 2, 2,                        /* 00 .. 07 */
-       3, 3, 3, 3, 3, 3, 3, 3,                 /* 08 .. 0f */
-       4, 4, 4, 4, 4, 4, 4, 4,                 /* 10 .. 17 */
-       4, 4, 4, 4, 4, 4, 4, 4,                 /* 18 .. 1f */
-       5, 5, 5, 5, 5, 5, 5, 5,                 /* 20 .. 27 */
-       5, 5, 5, 5, 5, 5, 5, 5,                 /* 28 .. 2f */
-       5, 5, 5, 5, 5, 5, 5, 5,                 /* 30 .. 37 */
-       5, 5, 5, 5, 5, 5, 5, 5,                 /* 38 .. 3f */
-       6, 6, 6, 6, 6, 6, 6, 6,                 /* 40 .. 47 */
-       6, 6, 6, 6, 6, 6, 6, 6,                 /* 48 .. 4f */
-       6, 6, 6, 6, 6, 6, 6, 6,                 /* 50 .. 57 */
-       6, 6, 6, 6, 6, 6, 6, 6,                 /* 58 .. 5f */
-       6, 6, 6, 6, 6, 6, 6, 6,                 /* 60 .. 67 */
-       6, 6, 6, 6, 6, 6, 6, 6,                 /* 68 .. 6f */
-       6, 6, 6, 6, 6, 6, 6, 6,                 /* 70 .. 77 */
-       6, 6, 6, 6, 6, 6, 6, 6,                 /* 78 .. 7f */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* 80 .. 87 */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* 88 .. 8f */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* 90 .. 97 */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* 98 .. 9f */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* a0 .. a7 */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* a8 .. af */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* b0 .. b7 */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* b8 .. bf */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* c0 .. c7 */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* c8 .. cf */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* d0 .. d7 */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* d8 .. df */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* e0 .. e7 */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* e8 .. ef */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* f0 .. f7 */
-       7, 7, 7, 7, 7, 7, 7, 7,                 /* f8 .. ff */
-};
-#endif
-
-/*
- * xfs_highbit32: get high bit set out of 32-bit argument, -1 if none set.
- */
-inline int
-xfs_highbit32(
-       __uint32_t      v)
-{
-#ifdef HAVE_ARCH_HIGHBIT
-       return highbit32(v);
-#else
-       int             i;
-
-       if (v & 0xffff0000)
-               if (v & 0xff000000)
-                       i = 24;
-               else
-                       i = 16;
-       else if (v & 0x0000ffff)
-               if (v & 0x0000ff00)
-                       i = 8;
-               else
-                       i = 0;
-       else
-               return -1;
-       return i + xfs_highbit[(v >> i) & 0xff];
-#endif
-}
-
-/*
- * xfs_lowbit64: get low bit set out of 64-bit argument, -1 if none set.
- */
-int
-xfs_lowbit64(
-       __uint64_t      v)
-{
-       __uint32_t      w = (__uint32_t)v;
-       int             n = 0;
-
-       if (w) {        /* lower bits */
-               n = ffs(w);
-       } else {        /* upper bits */
-               w = (__uint32_t)(v >> 32);
-               if (w && (n = ffs(w)))
-                       n += 32;
-       }
-       return n - 1;
-}
-
-/*
- * xfs_highbit64: get high bit set out of 64-bit argument, -1 if none set.
- */
-int
-xfs_highbit64(
-       __uint64_t      v)
-{
-       __uint32_t      h = (__uint32_t)(v >> 32);
-
-       if (h)
-               return xfs_highbit32(h) + 32;
-       return xfs_highbit32((__uint32_t)v);
-}
-
-
 /*
  * Return whether bitmap is empty.
  * Size is number of words in the bitmap, which is padded to word boundary
index 082641a9782c073e832fab360d88d98020f87310..8e0e463dae2d7c0f55268c46683110a01a42405b 100644 (file)
@@ -47,13 +47,39 @@ static inline __uint64_t xfs_mask64lo(int n)
 }
 
 /* Get high bit set out of 32-bit argument, -1 if none set */
-extern int xfs_highbit32(__uint32_t v);
+static inline int xfs_highbit32(__uint32_t v)
+{
+       return fls(v) - 1;
+}
+
+/* Get high bit set out of 64-bit argument, -1 if none set */
+static inline int xfs_highbit64(__uint64_t v)
+{
+       return fls64(v) - 1;
+}
+
+/* Get low bit set out of 32-bit argument, -1 if none set */
+static inline int xfs_lowbit32(__uint32_t v)
+{
+       unsigned long   t = v;
+       return (v) ? find_first_bit(&t, 32) : -1;
+}
 
 /* Get low bit set out of 64-bit argument, -1 if none set */
-extern int xfs_lowbit64(__uint64_t v);
+static inline int xfs_lowbit64(__uint64_t v)
+{
+       __uint32_t      w = (__uint32_t)v;
+       int             n = 0;
 
-/* Get high bit set out of 64-bit argument, -1 if none set */
-extern int xfs_highbit64(__uint64_t);
+       if (w) {        /* lower bits */
+               n = ffs(w);
+       } else {        /* upper bits */
+               w = (__uint32_t)(v >> 32);
+               if (w && (n = ffs(w)))
+               n += 32;
+       }
+       return n - 1;
+}
 
 /* Return whether bitmap is empty (1 == empty) */
 extern int xfs_bitmap_empty(uint *map, uint size);
index 3c4beb3a43266585c948f91fefe2a1a7adbb82ea..a1aab9275d5ac727700a00070b89c88e1acb8e42 100644 (file)
@@ -384,14 +384,14 @@ xfs_bmap_count_tree(
        int             levelin,
        int             *count);
 
-STATIC int
+STATIC void
 xfs_bmap_count_leaves(
        xfs_ifork_t             *ifp,
        xfs_extnum_t            idx,
        int                     numrecs,
        int                     *count);
 
-STATIC int
+STATIC void
 xfs_bmap_disk_count_leaves(
        xfs_extnum_t            idx,
        xfs_bmbt_block_t        *block,
@@ -4000,7 +4000,7 @@ xfs_bmap_add_attrfork(
                ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
        }
        ASSERT(ip->i_d.di_anextents == 0);
-       VN_HOLD(XFS_ITOV(ip));
+       IHOLD(ip);
        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        switch (ip->i_d.di_format) {
@@ -6096,7 +6096,7 @@ xfs_bmap_get_bp(
                tp = cur->bc_tp;
                licp = &tp->t_items;
                while (!bp && licp != NULL) {
-                       if (XFS_LIC_ARE_ALL_FREE(licp)) {
+                       if (xfs_lic_are_all_free(licp)) {
                                licp = licp->lic_next;
                                continue;
                        }
@@ -6106,11 +6106,11 @@ xfs_bmap_get_bp(
                                xfs_buf_log_item_t      *bip;
                                xfs_buf_t               *lbp;
 
-                               if (XFS_LIC_ISFREE(licp, i)) {
+                               if (xfs_lic_isfree(licp, i)) {
                                        continue;
                                }
 
-                               lidp = XFS_LIC_SLOT(licp, i);
+                               lidp = xfs_lic_slot(licp, i);
                                lip = lidp->lid_item;
                                if (lip->li_type != XFS_LI_BUF)
                                        continue;
@@ -6367,13 +6367,9 @@ xfs_bmap_count_blocks(
        mp = ip->i_mount;
        ifp = XFS_IFORK_PTR(ip, whichfork);
        if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) {
-               if (unlikely(xfs_bmap_count_leaves(ifp, 0,
+               xfs_bmap_count_leaves(ifp, 0,
                        ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t),
-                       count) < 0)) {
-                       XFS_ERROR_REPORT("xfs_bmap_count_blocks(1)",
-                                        XFS_ERRLEVEL_LOW, mp);
-                       return XFS_ERROR(EFSCORRUPTED);
-               }
+                       count);
                return 0;
        }
 
@@ -6454,13 +6450,7 @@ xfs_bmap_count_tree(
                for (;;) {
                        nextbno = be64_to_cpu(block->bb_rightsib);
                        numrecs = be16_to_cpu(block->bb_numrecs);
-                       if (unlikely(xfs_bmap_disk_count_leaves(0,
-                                       block, numrecs, count) < 0)) {
-                               xfs_trans_brelse(tp, bp);
-                               XFS_ERROR_REPORT("xfs_bmap_count_tree(2)",
-                                                XFS_ERRLEVEL_LOW, mp);
-                               return XFS_ERROR(EFSCORRUPTED);
-                       }
+                       xfs_bmap_disk_count_leaves(0, block, numrecs, count);
                        xfs_trans_brelse(tp, bp);
                        if (nextbno == NULLFSBLOCK)
                                break;
@@ -6478,7 +6468,7 @@ xfs_bmap_count_tree(
 /*
  * Count leaf blocks given a range of extent records.
  */
-STATIC int
+STATIC void
 xfs_bmap_count_leaves(
        xfs_ifork_t             *ifp,
        xfs_extnum_t            idx,
@@ -6491,14 +6481,13 @@ xfs_bmap_count_leaves(
                xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, idx + b);
                *count += xfs_bmbt_get_blockcount(frp);
        }
-       return 0;
 }
 
 /*
  * Count leaf blocks given a range of extent records originally
  * in btree format.
  */
-STATIC int
+STATIC void
 xfs_bmap_disk_count_leaves(
        xfs_extnum_t            idx,
        xfs_bmbt_block_t        *block,
@@ -6512,5 +6501,4 @@ xfs_bmap_disk_count_leaves(
                frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, idx + b);
                *count += xfs_bmbt_disk_get_blockcount(frp);
        }
-       return 0;
 }
index aeb87ca69fcc2e12e3042d21994b3ddbdd41fe75..cc593a84c34572211cc2ff44997457838bbe4f5d 100644 (file)
@@ -46,37 +46,10 @@ kmem_zone_t *xfs_btree_cur_zone;
 /*
  * Btree magic numbers.
  */
-const __uint32_t xfs_magics[XFS_BTNUM_MAX] =
-{
+const __uint32_t xfs_magics[XFS_BTNUM_MAX] = {
        XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC
 };
 
-/*
- * Prototypes for internal routines.
- */
-
-/*
- * Checking routine: return maxrecs for the block.
- */
-STATIC int                             /* number of records fitting in block */
-xfs_btree_maxrecs(
-       xfs_btree_cur_t         *cur,   /* btree cursor */
-       xfs_btree_block_t       *block);/* generic btree block pointer */
-
-/*
- * Internal routines.
- */
-
-/*
- * Retrieve the block pointer from the cursor at the given level.
- * This may be a bmap btree root or from a buffer.
- */
-STATIC xfs_btree_block_t *                     /* generic btree block pointer */
-xfs_btree_get_block(
-       xfs_btree_cur_t         *cur,   /* btree cursor */
-       int                     level,  /* level in btree */
-       struct xfs_buf          **bpp); /* buffer containing the block */
-
 /*
  * Checking routine: return maxrecs for the block.
  */
@@ -456,35 +429,6 @@ xfs_btree_dup_cursor(
        return 0;
 }
 
-/*
- * Change the cursor to point to the first record at the given level.
- * Other levels are unaffected.
- */
-int                                    /* success=1, failure=0 */
-xfs_btree_firstrec(
-       xfs_btree_cur_t         *cur,   /* btree cursor */
-       int                     level)  /* level to change */
-{
-       xfs_btree_block_t       *block; /* generic btree block pointer */
-       xfs_buf_t               *bp;    /* buffer containing block */
-
-       /*
-        * Get the block pointer for this level.
-        */
-       block = xfs_btree_get_block(cur, level, &bp);
-       xfs_btree_check_block(cur, block, level, bp);
-       /*
-        * It's empty, there is no such record.
-        */
-       if (!block->bb_h.bb_numrecs)
-               return 0;
-       /*
-        * Set the ptr value to 1, that's the first record/key.
-        */
-       cur->bc_ptrs[level] = 1;
-       return 1;
-}
-
 /*
  * Retrieve the block pointer from the cursor at the given level.
  * This may be a bmap btree root or from a buffer.
@@ -626,6 +570,13 @@ xfs_btree_init_cursor(
                cur->bc_private.a.agbp = agbp;
                cur->bc_private.a.agno = agno;
                break;
+       case XFS_BTNUM_INO:
+               /*
+                * Inode allocation btree fields.
+                */
+               cur->bc_private.a.agbp = agbp;
+               cur->bc_private.a.agno = agno;
+               break;
        case XFS_BTNUM_BMAP:
                /*
                 * Bmap btree fields.
@@ -638,13 +589,6 @@ xfs_btree_init_cursor(
                cur->bc_private.b.flags = 0;
                cur->bc_private.b.whichfork = whichfork;
                break;
-       case XFS_BTNUM_INO:
-               /*
-                * Inode allocation btree fields.
-                */
-               cur->bc_private.i.agbp = agbp;
-               cur->bc_private.i.agno = agno;
-               break;
        default:
                ASSERT(0);
        }
@@ -670,6 +614,35 @@ xfs_btree_islastblock(
                return be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK;
 }
 
+/*
+ * Change the cursor to point to the first record at the given level.
+ * Other levels are unaffected.
+ */
+int                                    /* success=1, failure=0 */
+xfs_btree_firstrec(
+       xfs_btree_cur_t         *cur,   /* btree cursor */
+       int                     level)  /* level to change */
+{
+       xfs_btree_block_t       *block; /* generic btree block pointer */
+       xfs_buf_t               *bp;    /* buffer containing block */
+
+       /*
+        * Get the block pointer for this level.
+        */
+       block = xfs_btree_get_block(cur, level, &bp);
+       xfs_btree_check_block(cur, block, level, bp);
+       /*
+        * It's empty, there is no such record.
+        */
+       if (!block->bb_h.bb_numrecs)
+               return 0;
+       /*
+        * Set the ptr value to 1, that's the first record/key.
+        */
+       cur->bc_ptrs[level] = 1;
+       return 1;
+}
+
 /*
  * Change the cursor to point to the last record in the current block
  * at the given level.  Other levels are unaffected.
@@ -890,12 +863,12 @@ xfs_btree_readahead_core(
        case XFS_BTNUM_INO:
                i = XFS_BUF_TO_INOBT_BLOCK(cur->bc_bufs[lev]);
                if ((lr & XFS_BTCUR_LEFTRA) && be32_to_cpu(i->bb_leftsib) != NULLAGBLOCK) {
-                       xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno,
+                       xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
                                be32_to_cpu(i->bb_leftsib), 1);
                        rval++;
                }
                if ((lr & XFS_BTCUR_RIGHTRA) && be32_to_cpu(i->bb_rightsib) != NULLAGBLOCK) {
-                       xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno,
+                       xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
                                be32_to_cpu(i->bb_rightsib), 1);
                        rval++;
                }
index 7440b78f9cec3b6d5c722e804b3fbc5acca756c8..1f528a2a37545d858d40577a948e56ee7699d479 100644 (file)
@@ -158,8 +158,8 @@ typedef struct xfs_btree_cur
        __uint8_t       bc_blocklog;    /* log2(blocksize) of btree blocks */
        xfs_btnum_t     bc_btnum;       /* identifies which btree type */
        union {
-               struct {                        /* needed for BNO, CNT */
-                       struct xfs_buf  *agbp;  /* agf buffer pointer */
+               struct {                        /* needed for BNO, CNT, INO */
+                       struct xfs_buf  *agbp;  /* agf/agi buffer pointer */
                        xfs_agnumber_t  agno;   /* ag number */
                } a;
                struct {                        /* needed for BMAP */
@@ -172,10 +172,6 @@ typedef struct xfs_btree_cur
                        char            flags;          /* flags */
 #define        XFS_BTCUR_BPRV_WASDEL   1                       /* was delayed */
                } b;
-               struct {                        /* needed for INO */
-                       struct xfs_buf  *agbp;  /* agi buffer pointer */
-                       xfs_agnumber_t  agno;   /* ag number */
-               } i;
        }               bc_private;     /* per-btree type data */
 } xfs_btree_cur_t;
 
index d86ca2c03a70d596ae42f2028faa932549ba1601..608c30c3f76b872b8e553d325364407eff489593 100644 (file)
@@ -737,7 +737,7 @@ xfs_buf_item_init(
        bip->bli_format.blf_len = (ushort)BTOBB(XFS_BUF_COUNT(bp));
        bip->bli_format.blf_map_size = map_size;
 #ifdef XFS_BLI_TRACE
-       bip->bli_trace = ktrace_alloc(XFS_BLI_TRACE_SIZE, KM_SLEEP);
+       bip->bli_trace = ktrace_alloc(XFS_BLI_TRACE_SIZE, KM_NOFS);
 #endif
 
 #ifdef XFS_TRANS_DEBUG
@@ -1056,7 +1056,7 @@ xfs_buf_iodone_callbacks(
                           anyway. */
                        XFS_BUF_SET_BRELSE_FUNC(bp,xfs_buf_error_relse);
                        XFS_BUF_DONE(bp);
-                       XFS_BUF_V_IODONESEMA(bp);
+                       XFS_BUF_FINISH_IOWAIT(bp);
                }
                return;
        }
index 2211e885ef243d47d690bb9a4bf044cf9bf26504..760f4c5b5160c4e648e17d491d8912c691726214 100644 (file)
@@ -128,10 +128,8 @@ xfs_swap_extents(
        xfs_swapext_t   *sxp)
 {
        xfs_mount_t     *mp;
-       xfs_inode_t     *ips[2];
        xfs_trans_t     *tp;
        xfs_bstat_t     *sbp = &sxp->sx_stat;
-       bhv_vnode_t     *vp, *tvp;
        xfs_ifork_t     *tempifp, *ifp, *tifp;
        int             ilf_fields, tilf_fields;
        static uint     lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;
@@ -150,19 +148,8 @@ xfs_swap_extents(
        }
 
        sbp = &sxp->sx_stat;
-       vp = XFS_ITOV(ip);
-       tvp = XFS_ITOV(tip);
-
-       /* Lock in i_ino order */
-       if (ip->i_ino < tip->i_ino) {
-               ips[0] = ip;
-               ips[1] = tip;
-       } else {
-               ips[0] = tip;
-               ips[1] = ip;
-       }
 
-       xfs_lock_inodes(ips, 2, lock_flags);
+       xfs_lock_two_inodes(ip, tip, lock_flags);
        locked = 1;
 
        /* Verify that both files have the same format */
@@ -184,7 +171,7 @@ xfs_swap_extents(
                goto error0;
        }
 
-       if (VN_CACHED(tvp) != 0) {
+       if (VN_CACHED(VFS_I(tip)) != 0) {
                xfs_inval_cached_trace(tip, 0, -1, 0, -1);
                error = xfs_flushinval_pages(tip, 0, -1,
                                FI_REMAPF_LOCKED);
@@ -193,7 +180,7 @@ xfs_swap_extents(
        }
 
        /* Verify O_DIRECT for ftmp */
-       if (VN_CACHED(tvp) != 0) {
+       if (VN_CACHED(VFS_I(tip)) != 0) {
                error = XFS_ERROR(EINVAL);
                goto error0;
        }
@@ -237,7 +224,7 @@ xfs_swap_extents(
         * vop_read (or write in the case of autogrow) they block on the iolock
         * until we have switched the extents.
         */
-       if (VN_MAPPED(vp)) {
+       if (VN_MAPPED(VFS_I(ip))) {
                error = XFS_ERROR(EBUSY);
                goto error0;
        }
@@ -265,7 +252,7 @@ xfs_swap_extents(
                locked = 0;
                goto error0;
        }
-       xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL);
+       xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);
 
        /*
         * Count the number of extended attribute blocks
@@ -350,15 +337,11 @@ xfs_swap_extents(
                break;
        }
 
-       /*
-        * Increment vnode ref counts since xfs_trans_commit &
-        * xfs_trans_cancel will both unlock the inodes and
-        * decrement the associated ref counts.
-        */
-       VN_HOLD(vp);
-       VN_HOLD(tvp);
 
+       IHOLD(ip);
        xfs_trans_ijoin(tp, ip, lock_flags);
+
+       IHOLD(tip);
        xfs_trans_ijoin(tp, tip, lock_flags);
 
        xfs_trans_log_inode(tp, ip,  ilf_fields);
index f66756cfb5e8c0c327305212910c53eba7c98443..f227ecd1a2942714e1d062c142c27f14781613a1 100644 (file)
@@ -58,9 +58,6 @@ xfs_error_trap(int e)
        }
        return e;
 }
-#endif
-
-#if (defined(DEBUG) || defined(INDUCE_IO_ERROR))
 
 int    xfs_etest[XFS_NUM_INJECT_ERROR];
 int64_t        xfs_etest_fsid[XFS_NUM_INJECT_ERROR];
@@ -154,7 +151,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud)
 
        return 0;
 }
-#endif /* DEBUG || INDUCE_IO_ERROR */
+#endif /* DEBUG */
 
 static void
 xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap)
index d8559d132efae28c5797ef2a898f0342d454463c..11543f10b0c6d10780846dcf1fedd65b3821f192 100644 (file)
@@ -125,22 +125,14 @@ extern void xfs_corruption_error(char *tag, int level, struct xfs_mount *mp,
 #define XFS_RANDOM_DIOWRITE_IOERR                      (XFS_RANDOM_DEFAULT/10)
 #define        XFS_RANDOM_BMAPIFORMAT                          XFS_RANDOM_DEFAULT
 
-#if (defined(DEBUG) || defined(INDUCE_IO_ERROR))
+#ifdef DEBUG
 extern int xfs_error_test(int, int *, char *, int, char *, unsigned long);
 
 #define        XFS_NUM_INJECT_ERROR                            10
-
-#ifdef __ANSI_CPP__
-#define XFS_TEST_ERROR(expr, mp, tag, rf)              \
-       ((expr) || \
-        xfs_error_test((tag), (mp)->m_fixedfsid, #expr, __LINE__, __FILE__, \
-                        (rf)))
-#else
 #define XFS_TEST_ERROR(expr, mp, tag, rf)              \
        ((expr) || \
         xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \
                        (rf)))
-#endif /* __ANSI_CPP__ */
 
 extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp);
 extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud);
@@ -148,7 +140,7 @@ extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud);
 #define XFS_TEST_ERROR(expr, mp, tag, rf)      (expr)
 #define xfs_errortag_add(tag, mp)              (ENOSYS)
 #define xfs_errortag_clearall(mp, loud)                (ENOSYS)
-#endif /* (DEBUG || INDUCE_IO_ERROR) */
+#endif /* DEBUG */
 
 /*
  * XFS panic tags -- allow a call to xfs_cmn_err() be turned into
index c38fd14fca29c7821001d6eca11df641b466908a..f3bb75da384e0919d30b6ba4722875ffe5736da3 100644 (file)
@@ -400,7 +400,7 @@ xfs_filestream_init(void)
        if (!item_zone)
                return -ENOMEM;
 #ifdef XFS_FILESTREAMS_TRACE
-       xfs_filestreams_trace_buf = ktrace_alloc(XFS_FSTRM_KTRACE_SIZE, KM_SLEEP);
+       xfs_filestreams_trace_buf = ktrace_alloc(XFS_FSTRM_KTRACE_SIZE, KM_NOFS);
 #endif
        return 0;
 }
index e5310c90e50fc3dbe078b567c5a500cd1047f9e4..83502f3edef0d99477e6fb539418950ec9019c9b 100644 (file)
@@ -181,7 +181,7 @@ xfs_inobt_delrec(
                 * then we can get rid of this level.
                 */
                if (numrecs == 1 && level > 0) {
-                       agbp = cur->bc_private.i.agbp;
+                       agbp = cur->bc_private.a.agbp;
                        agi = XFS_BUF_TO_AGI(agbp);
                        /*
                         * pp is still set to the first pointer in the block.
@@ -194,7 +194,7 @@ xfs_inobt_delrec(
                         * Free the block.
                         */
                        if ((error = xfs_free_extent(cur->bc_tp,
-                               XFS_AGB_TO_FSB(mp, cur->bc_private.i.agno, bno), 1)))
+                               XFS_AGB_TO_FSB(mp, cur->bc_private.a.agno, bno), 1)))
                                return error;
                        xfs_trans_binval(cur->bc_tp, bp);
                        xfs_ialloc_log_agi(cur->bc_tp, agbp,
@@ -379,7 +379,7 @@ xfs_inobt_delrec(
                rrecs = be16_to_cpu(right->bb_numrecs);
                rbp = bp;
                if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
-                               cur->bc_private.i.agno, lbno, 0, &lbp,
+                               cur->bc_private.a.agno, lbno, 0, &lbp,
                                XFS_INO_BTREE_REF)))
                        return error;
                left = XFS_BUF_TO_INOBT_BLOCK(lbp);
@@ -401,7 +401,7 @@ xfs_inobt_delrec(
                lrecs = be16_to_cpu(left->bb_numrecs);
                lbp = bp;
                if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
-                               cur->bc_private.i.agno, rbno, 0, &rbp,
+                               cur->bc_private.a.agno, rbno, 0, &rbp,
                                XFS_INO_BTREE_REF)))
                        return error;
                right = XFS_BUF_TO_INOBT_BLOCK(rbp);
@@ -484,7 +484,7 @@ xfs_inobt_delrec(
                xfs_buf_t               *rrbp;
 
                if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
-                               cur->bc_private.i.agno, be32_to_cpu(left->bb_rightsib), 0,
+                               cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib), 0,
                                &rrbp, XFS_INO_BTREE_REF)))
                        return error;
                rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp);
@@ -497,7 +497,7 @@ xfs_inobt_delrec(
         * Free the deleting block.
         */
        if ((error = xfs_free_extent(cur->bc_tp, XFS_AGB_TO_FSB(mp,
-                                    cur->bc_private.i.agno, rbno), 1)))
+                                    cur->bc_private.a.agno, rbno), 1)))
                return error;
        xfs_trans_binval(cur->bc_tp, rbp);
        /*
@@ -854,7 +854,7 @@ xfs_inobt_lookup(
        {
                xfs_agi_t       *agi;   /* a.g. inode header */
 
-               agi = XFS_BUF_TO_AGI(cur->bc_private.i.agbp);
+               agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp);
                agno = be32_to_cpu(agi->agi_seqno);
                agbno = be32_to_cpu(agi->agi_root);
        }
@@ -1089,7 +1089,7 @@ xfs_inobt_lshift(
         * Set up the left neighbor as "left".
         */
        if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
-                       cur->bc_private.i.agno, be32_to_cpu(right->bb_leftsib),
+                       cur->bc_private.a.agno, be32_to_cpu(right->bb_leftsib),
                        0, &lbp, XFS_INO_BTREE_REF)))
                return error;
        left = XFS_BUF_TO_INOBT_BLOCK(lbp);
@@ -1207,10 +1207,10 @@ xfs_inobt_newroot(
        /*
         * Get a block & a buffer.
         */
-       agi = XFS_BUF_TO_AGI(cur->bc_private.i.agbp);
+       agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp);
        args.tp = cur->bc_tp;
        args.mp = cur->bc_mp;
-       args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.i.agno,
+       args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno,
                be32_to_cpu(agi->agi_root));
        args.mod = args.minleft = args.alignment = args.total = args.wasdel =
                args.isfl = args.userdata = args.minalignslop = 0;
@@ -1233,7 +1233,7 @@ xfs_inobt_newroot(
         */
        agi->agi_root = cpu_to_be32(args.agbno);
        be32_add_cpu(&agi->agi_level, 1);
-       xfs_ialloc_log_agi(args.tp, cur->bc_private.i.agbp,
+       xfs_ialloc_log_agi(args.tp, cur->bc_private.a.agbp,
                XFS_AGI_ROOT | XFS_AGI_LEVEL);
        /*
         * At the previous root level there are now two blocks: the old
@@ -1376,7 +1376,7 @@ xfs_inobt_rshift(
         * Set up the right neighbor as "right".
         */
        if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
-                       cur->bc_private.i.agno, be32_to_cpu(left->bb_rightsib),
+                       cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib),
                        0, &rbp, XFS_INO_BTREE_REF)))
                return error;
        right = XFS_BUF_TO_INOBT_BLOCK(rbp);
@@ -1492,7 +1492,7 @@ xfs_inobt_split(
         * Allocate the new block.
         * If we can't do it, we're toast.  Give up.
         */
-       args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.i.agno, lbno);
+       args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, lbno);
        args.mod = args.minleft = args.alignment = args.total = args.wasdel =
                args.isfl = args.userdata = args.minalignslop = 0;
        args.minlen = args.maxlen = args.prod = 1;
@@ -1725,7 +1725,7 @@ xfs_inobt_decrement(
 
                agbno = be32_to_cpu(*XFS_INOBT_PTR_ADDR(block, cur->bc_ptrs[lev], cur));
                if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
-                               cur->bc_private.i.agno, agbno, 0, &bp,
+                               cur->bc_private.a.agno, agbno, 0, &bp,
                                XFS_INO_BTREE_REF)))
                        return error;
                lev--;
@@ -1897,7 +1897,7 @@ xfs_inobt_increment(
 
                agbno = be32_to_cpu(*XFS_INOBT_PTR_ADDR(block, cur->bc_ptrs[lev], cur));
                if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
-                               cur->bc_private.i.agno, agbno, 0, &bp,
+                               cur->bc_private.a.agno, agbno, 0, &bp,
                                XFS_INO_BTREE_REF)))
                        return error;
                lev--;
index b07604b94d9f32c2f15e7eb08c5e83b458b3fd42..e229e9e001c291fa556c043cf79c9070743675e7 100644 (file)
@@ -216,7 +216,14 @@ finish_inode:
        mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
        init_waitqueue_head(&ip->i_ipin_wait);
        atomic_set(&ip->i_pincount, 0);
-       initnsema(&ip->i_flock, 1, "xfsfino");
+
+       /*
+        * Because we want to use a counting completion, complete
+        * the flush completion once to allow a single access to
+        * the flush completion without blocking.
+        */
+       init_completion(&ip->i_flush);
+       complete(&ip->i_flush);
 
        if (lock_flags)
                xfs_ilock(ip, lock_flags);
@@ -287,11 +294,18 @@ finish_inode:
        xfs_iflags_set(ip, XFS_IMODIFIED);
        *ipp = ip;
 
+       /*
+        * Set up the Linux with the Linux inode.
+        */
+       ip->i_vnode = inode;
+       inode->i_private = ip;
+
        /*
         * If we have a real type for an on-disk inode, we can set ops(&unlock)
         * now.  If it's a new inode being created, xfs_ialloc will handle it.
         */
-       xfs_initialize_vnode(mp, inode, ip);
+       if (ip->i_d.di_mode != 0)
+               xfs_setup_inode(ip);
        return 0;
 }
 
@@ -411,10 +425,11 @@ xfs_iput(xfs_inode_t      *ip,
  * Special iput for brand-new inodes that are still locked
  */
 void
-xfs_iput_new(xfs_inode_t       *ip,
-            uint               lock_flags)
+xfs_iput_new(
+       xfs_inode_t     *ip,
+       uint            lock_flags)
 {
-       struct inode    *inode = ip->i_vnode;
+       struct inode    *inode = VFS_I(ip);
 
        xfs_itrace_entry(ip);
 
@@ -775,26 +790,3 @@ xfs_isilocked(
 }
 #endif
 
-/*
- * The following three routines simply manage the i_flock
- * semaphore embedded in the inode.  This semaphore synchronizes
- * processes attempting to flush the in-core inode back to disk.
- */
-void
-xfs_iflock(xfs_inode_t *ip)
-{
-       psema(&(ip->i_flock), PINOD|PLTWAIT);
-}
-
-int
-xfs_iflock_nowait(xfs_inode_t *ip)
-{
-       return (cpsema(&(ip->i_flock)));
-}
-
-void
-xfs_ifunlock(xfs_inode_t *ip)
-{
-       ASSERT(issemalocked(&(ip->i_flock)));
-       vsema(&(ip->i_flock));
-}
index bedc66163176484b5dc7e7911637ab0059e6c0a8..00e80df9dd9d727191f15fefc79cd92055d4e9d6 100644 (file)
@@ -580,8 +580,8 @@ xfs_iformat_extents(
                xfs_validate_extents(ifp, nex, XFS_EXTFMT_INODE(ip));
                for (i = 0; i < nex; i++, dp++) {
                        xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
-                       ep->l0 = be64_to_cpu(get_unaligned(&dp->l0));
-                       ep->l1 = be64_to_cpu(get_unaligned(&dp->l1));
+                       ep->l0 = get_unaligned_be64(&dp->l0);
+                       ep->l1 = get_unaligned_be64(&dp->l1);
                }
                XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork);
                if (whichfork != XFS_DATA_FORK ||
@@ -835,22 +835,22 @@ xfs_iread(
         * Do this before xfs_iformat in case it adds entries.
         */
 #ifdef XFS_INODE_TRACE
-       ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_SLEEP);
+       ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_NOFS);
 #endif
 #ifdef XFS_BMAP_TRACE
-       ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_SLEEP);
+       ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_NOFS);
 #endif
 #ifdef XFS_BMBT_TRACE
-       ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_SLEEP);
+       ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_NOFS);
 #endif
 #ifdef XFS_RW_TRACE
-       ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_SLEEP);
+       ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_NOFS);
 #endif
 #ifdef XFS_ILOCK_TRACE
-       ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_SLEEP);
+       ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_NOFS);
 #endif
 #ifdef XFS_DIR2_TRACE
-       ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_SLEEP);
+       ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS);
 #endif
 
        /*
@@ -1046,9 +1046,9 @@ xfs_ialloc(
 {
        xfs_ino_t       ino;
        xfs_inode_t     *ip;
-       bhv_vnode_t     *vp;
        uint            flags;
        int             error;
+       timespec_t      tv;
 
        /*
         * Call the space management code to pick
@@ -1077,13 +1077,12 @@ xfs_ialloc(
        }
        ASSERT(ip != NULL);
 
-       vp = XFS_ITOV(ip);
        ip->i_d.di_mode = (__uint16_t)mode;
        ip->i_d.di_onlink = 0;
        ip->i_d.di_nlink = nlink;
        ASSERT(ip->i_d.di_nlink == nlink);
-       ip->i_d.di_uid = current_fsuid(cr);
-       ip->i_d.di_gid = current_fsgid(cr);
+       ip->i_d.di_uid = current_fsuid();
+       ip->i_d.di_gid = current_fsgid();
        ip->i_d.di_projid = prid;
        memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
 
@@ -1130,7 +1129,13 @@ xfs_ialloc(
        ip->i_size = 0;
        ip->i_d.di_nextents = 0;
        ASSERT(ip->i_d.di_nblocks == 0);
-       xfs_ichgtime(ip, XFS_ICHGTIME_CHG|XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD);
+
+       nanotime(&tv);
+       ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
+       ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
+       ip->i_d.di_atime = ip->i_d.di_mtime;
+       ip->i_d.di_ctime = ip->i_d.di_mtime;
+
        /*
         * di_gen will have been taken care of in xfs_iread.
         */
@@ -1220,7 +1225,7 @@ xfs_ialloc(
        xfs_trans_log_inode(tp, ip, flags);
 
        /* now that we have an i_mode we can setup inode ops and unlock */
-       xfs_initialize_vnode(tp->t_mountp, vp, ip);
+       xfs_setup_inode(ip);
 
        *ipp = ip;
        return 0;
@@ -1399,7 +1404,6 @@ xfs_itruncate_start(
        xfs_fsize_t     last_byte;
        xfs_off_t       toss_start;
        xfs_mount_t     *mp;
-       bhv_vnode_t     *vp;
        int             error = 0;
 
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
@@ -1408,7 +1412,6 @@ xfs_itruncate_start(
               (flags == XFS_ITRUNC_MAYBE));
 
        mp = ip->i_mount;
-       vp = XFS_ITOV(ip);
 
        /* wait for the completion of any pending DIOs */
        if (new_size < ip->i_size)
@@ -1457,7 +1460,7 @@ xfs_itruncate_start(
 
 #ifdef DEBUG
        if (new_size == 0) {
-               ASSERT(VN_CACHED(vp) == 0);
+               ASSERT(VN_CACHED(VFS_I(ip)) == 0);
        }
 #endif
        return error;
@@ -2630,7 +2633,6 @@ xfs_idestroy(
                xfs_idestroy_fork(ip, XFS_ATTR_FORK);
        mrfree(&ip->i_lock);
        mrfree(&ip->i_iolock);
-       freesema(&ip->i_flock);
 
 #ifdef XFS_INODE_TRACE
        ktrace_free(ip->i_trace);
@@ -3048,10 +3050,10 @@ cluster_corrupt_out:
 /*
  * xfs_iflush() will write a modified inode's changes out to the
  * inode's on disk home.  The caller must have the inode lock held
- * in at least shared mode and the inode flush semaphore must be
- * held as well.  The inode lock will still be held upon return from
+ * in at least shared mode and the inode flush completion must be
+ * active as well.  The inode lock will still be held upon return from
  * the call and the caller is free to unlock it.
- * The inode flush lock will be unlocked when the inode reaches the disk.
+ * The inode flush will be completed when the inode reaches the disk.
  * The flags indicate how the inode's buffer should be written out.
  */
 int
@@ -3070,7 +3072,7 @@ xfs_iflush(
        XFS_STATS_INC(xs_iflush_count);
 
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
-       ASSERT(issemalocked(&(ip->i_flock)));
+       ASSERT(!completion_done(&ip->i_flush));
        ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
               ip->i_d.di_nextents > ip->i_df.if_ext_max);
 
@@ -3233,7 +3235,7 @@ xfs_iflush_int(
 #endif
 
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
-       ASSERT(issemalocked(&(ip->i_flock)));
+       ASSERT(!completion_done(&ip->i_flush));
        ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
               ip->i_d.di_nextents > ip->i_df.if_ext_max);
 
@@ -3465,7 +3467,6 @@ xfs_iflush_all(
        xfs_mount_t     *mp)
 {
        xfs_inode_t     *ip;
-       bhv_vnode_t     *vp;
 
  again:
        XFS_MOUNT_ILOCK(mp);
@@ -3480,14 +3481,13 @@ xfs_iflush_all(
                        continue;
                }
 
-               vp = XFS_ITOV_NULL(ip);
-               if (!vp) {
+               if (!VFS_I(ip)) {
                        XFS_MOUNT_IUNLOCK(mp);
                        xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
                        goto again;
                }
 
-               ASSERT(vn_count(vp) == 0);
+               ASSERT(vn_count(VFS_I(ip)) == 0);
 
                ip = ip->i_mnext;
        } while (ip != mp->m_inodes);
@@ -3707,7 +3707,7 @@ xfs_iext_add_indirect_multi(
         * (all extents past */
        if (nex2) {
                byte_diff = nex2 * sizeof(xfs_bmbt_rec_t);
-               nex2_ep = (xfs_bmbt_rec_t *) kmem_alloc(byte_diff, KM_SLEEP);
+               nex2_ep = (xfs_bmbt_rec_t *) kmem_alloc(byte_diff, KM_NOFS);
                memmove(nex2_ep, &erp->er_extbuf[idx], byte_diff);
                erp->er_extcount -= nex2;
                xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, -nex2);
@@ -4007,8 +4007,7 @@ xfs_iext_realloc_direct(
                        ifp->if_u1.if_extents =
                                kmem_realloc(ifp->if_u1.if_extents,
                                                rnew_size,
-                                               ifp->if_real_bytes,
-                                               KM_SLEEP);
+                                               ifp->if_real_bytes, KM_NOFS);
                }
                if (rnew_size > ifp->if_real_bytes) {
                        memset(&ifp->if_u1.if_extents[ifp->if_bytes /
@@ -4067,7 +4066,7 @@ xfs_iext_inline_to_direct(
        xfs_ifork_t     *ifp,           /* inode fork pointer */
        int             new_size)       /* number of extents in file */
 {
-       ifp->if_u1.if_extents = kmem_alloc(new_size, KM_SLEEP);
+       ifp->if_u1.if_extents = kmem_alloc(new_size, KM_NOFS);
        memset(ifp->if_u1.if_extents, 0, new_size);
        if (ifp->if_bytes) {
                memcpy(ifp->if_u1.if_extents, ifp->if_u2.if_inline_ext,
@@ -4099,7 +4098,7 @@ xfs_iext_realloc_indirect(
        } else {
                ifp->if_u1.if_ext_irec = (xfs_ext_irec_t *)
                        kmem_realloc(ifp->if_u1.if_ext_irec,
-                               new_size, size, KM_SLEEP);
+                               new_size, size, KM_NOFS);
        }
 }
 
@@ -4341,11 +4340,10 @@ xfs_iext_irec_init(
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
        ASSERT(nextents <= XFS_LINEAR_EXTS);
 
-       erp = (xfs_ext_irec_t *)
-               kmem_alloc(sizeof(xfs_ext_irec_t), KM_SLEEP);
+       erp = kmem_alloc(sizeof(xfs_ext_irec_t), KM_NOFS);
 
        if (nextents == 0) {
-               ifp->if_u1.if_extents = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
+               ifp->if_u1.if_extents = kmem_alloc(XFS_IEXT_BUFSZ, KM_NOFS);
        } else if (!ifp->if_real_bytes) {
                xfs_iext_inline_to_direct(ifp, XFS_IEXT_BUFSZ);
        } else if (ifp->if_real_bytes < XFS_IEXT_BUFSZ) {
@@ -4393,7 +4391,7 @@ xfs_iext_irec_new(
 
        /* Initialize new extent record */
        erp = ifp->if_u1.if_ext_irec;
-       erp[erp_idx].er_extbuf = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
+       erp[erp_idx].er_extbuf = kmem_alloc(XFS_IEXT_BUFSZ, KM_NOFS);
        ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ;
        memset(erp[erp_idx].er_extbuf, 0, XFS_IEXT_BUFSZ);
        erp[erp_idx].er_extcount = 0;
index 17a04b6321ed7c0264ff8795f55e6bfc445cbc3f..1420c49674d7451f196fabbd1df76b731dfc7703 100644 (file)
@@ -87,8 +87,7 @@ typedef struct xfs_ifork {
  * Flags for xfs_ichgtime().
  */
 #define        XFS_ICHGTIME_MOD        0x1     /* data fork modification timestamp */
-#define        XFS_ICHGTIME_ACC        0x2     /* data fork access timestamp */
-#define        XFS_ICHGTIME_CHG        0x4     /* inode field change timestamp */
+#define        XFS_ICHGTIME_CHG        0x2     /* inode field change timestamp */
 
 /*
  * Per-fork incore inode flags.
@@ -204,7 +203,7 @@ typedef struct xfs_inode {
        struct xfs_inode        *i_mprev;       /* ptr to prev inode */
        struct xfs_mount        *i_mount;       /* fs mount struct ptr */
        struct list_head        i_reclaim;      /* reclaim list */
-       bhv_vnode_t             *i_vnode;       /* vnode backpointer */
+       struct inode            *i_vnode;       /* vnode backpointer */
        struct xfs_dquot        *i_udquot;      /* user dquot */
        struct xfs_dquot        *i_gdquot;      /* group dquot */
 
@@ -223,7 +222,7 @@ typedef struct xfs_inode {
        struct xfs_inode_log_item *i_itemp;     /* logging information */
        mrlock_t                i_lock;         /* inode lock */
        mrlock_t                i_iolock;       /* inode IO lock */
-       sema_t                  i_flock;        /* inode flush lock */
+       struct completion       i_flush;        /* inode flush completion q */
        atomic_t                i_pincount;     /* inode pin count */
        wait_queue_head_t       i_ipin_wait;    /* inode pinning wait queue */
        spinlock_t              i_flags_lock;   /* inode i_flags lock */
@@ -263,6 +262,18 @@ typedef struct xfs_inode {
 #define XFS_ISIZE(ip)  (((ip)->i_d.di_mode & S_IFMT) == S_IFREG) ? \
                                (ip)->i_size : (ip)->i_d.di_size;
 
+/* Convert from vfs inode to xfs inode */
+static inline struct xfs_inode *XFS_I(struct inode *inode)
+{
+       return (struct xfs_inode *)inode->i_private;
+}
+
+/* convert from xfs inode to vfs inode */
+static inline struct inode *VFS_I(struct xfs_inode *ip)
+{
+       return (struct inode *)ip->i_vnode;
+}
+
 /*
  * i_flags helper functions
  */
@@ -439,9 +450,6 @@ xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags)
 #define        XFS_ITRUNC_DEFINITE     0x1
 #define        XFS_ITRUNC_MAYBE        0x2
 
-#define        XFS_ITOV(ip)            ((ip)->i_vnode)
-#define        XFS_ITOV_NULL(ip)       ((ip)->i_vnode)
-
 /*
  * For multiple groups support: if S_ISGID bit is set in the parent
  * directory, group of new file is set to that of the parent, and
@@ -473,11 +481,8 @@ int                xfs_ilock_nowait(xfs_inode_t *, uint);
 void           xfs_iunlock(xfs_inode_t *, uint);
 void           xfs_ilock_demote(xfs_inode_t *, uint);
 int            xfs_isilocked(xfs_inode_t *, uint);
-void           xfs_iflock(xfs_inode_t *);
-int            xfs_iflock_nowait(xfs_inode_t *);
 uint           xfs_ilock_map_shared(xfs_inode_t *);
 void           xfs_iunlock_map_shared(xfs_inode_t *, uint);
-void           xfs_ifunlock(xfs_inode_t *);
 void           xfs_ireclaim(xfs_inode_t *);
 int            xfs_finish_reclaim(xfs_inode_t *, int, int);
 int            xfs_finish_reclaim_all(struct xfs_mount *, int);
@@ -522,6 +527,7 @@ void                xfs_iflush_all(struct xfs_mount *);
 void           xfs_ichgtime(xfs_inode_t *, int);
 xfs_fsize_t    xfs_file_last_byte(xfs_inode_t *);
 void           xfs_lock_inodes(xfs_inode_t **, int, uint);
+void           xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint);
 
 void           xfs_synchronize_atime(xfs_inode_t *);
 void           xfs_mark_inode_dirty_sync(xfs_inode_t *);
@@ -570,6 +576,26 @@ extern struct kmem_zone    *xfs_ifork_zone;
 extern struct kmem_zone        *xfs_inode_zone;
 extern struct kmem_zone        *xfs_ili_zone;
 
+/*
+ * Manage the i_flush queue embedded in the inode.  This completion
+ * queue synchronizes processes attempting to flush the in-core
+ * inode back to disk.
+ */
+static inline void xfs_iflock(xfs_inode_t *ip)
+{
+       wait_for_completion(&ip->i_flush);
+}
+
+static inline int xfs_iflock_nowait(xfs_inode_t *ip)
+{
+       return try_wait_for_completion(&ip->i_flush);
+}
+
+static inline void xfs_ifunlock(xfs_inode_t *ip)
+{
+       complete(&ip->i_flush);
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* __XFS_INODE_H__ */
index 0eee08a32c269d88e04207c2773bf717528626cb..97c7452e2620ee56040c03a6b8bb09fdfb4cc854 100644 (file)
@@ -779,11 +779,10 @@ xfs_inode_item_pushbuf(
        ASSERT(iip->ili_push_owner == current_pid());
 
        /*
-        * If flushlock isn't locked anymore, chances are that the
-        * inode flush completed and the inode was taken off the AIL.
-        * So, just get out.
+        * If a flush is not in progress anymore, chances are that the
+        * inode was taken off the AIL. So, just get out.
         */
-       if (!issemalocked(&(ip->i_flock)) ||
+       if (completion_done(&ip->i_flush) ||
            ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) {
                iip->ili_pushbuf_flag = 0;
                xfs_iunlock(ip, XFS_ILOCK_SHARED);
@@ -805,7 +804,7 @@ xfs_inode_item_pushbuf(
                         * If not, we can flush it async.
                         */
                        dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) &&
-                                 issemalocked(&(ip->i_flock)));
+                                 !completion_done(&ip->i_flush));
                        iip->ili_pushbuf_flag = 0;
                        xfs_iunlock(ip, XFS_ILOCK_SHARED);
                        xfs_buftrace("INODE ITEM PUSH", bp);
@@ -858,7 +857,7 @@ xfs_inode_item_push(
        ip = iip->ili_inode;
 
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED));
-       ASSERT(issemalocked(&(ip->i_flock)));
+       ASSERT(!completion_done(&ip->i_flush));
        /*
         * Since we were able to lock the inode's flush lock and
         * we found it on the AIL, the inode must be dirty.  This
index 9a3ef9dcaeb9063b9be707c4e3f4ea8098822d20..cf6754a3c5b3e07a1e660c11ead329de21ef314c 100644 (file)
@@ -59,7 +59,6 @@ xfs_bulkstat_one_iget(
 {
        xfs_icdinode_t  *dic;   /* dinode core info pointer */
        xfs_inode_t     *ip;            /* incore inode pointer */
-       bhv_vnode_t     *vp;
        int             error;
 
        error = xfs_iget(mp, NULL, ino,
@@ -72,7 +71,6 @@ xfs_bulkstat_one_iget(
        ASSERT(ip != NULL);
        ASSERT(ip->i_blkno != (xfs_daddr_t)0);
 
-       vp = XFS_ITOV(ip);
        dic = &ip->i_d;
 
        /* xfs_iget returns the following without needing
@@ -85,7 +83,7 @@ xfs_bulkstat_one_iget(
        buf->bs_uid = dic->di_uid;
        buf->bs_gid = dic->di_gid;
        buf->bs_size = dic->di_size;
-       vn_atime_to_bstime(vp, &buf->bs_atime);
+       vn_atime_to_bstime(VFS_I(ip), &buf->bs_atime);
        buf->bs_mtime.tv_sec = dic->di_mtime.t_sec;
        buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec;
        buf->bs_ctime.tv_sec = dic->di_ctime.t_sec;
index 91b00a5686cd5331c5ce1a9221f066c5b4cc4cd7..ccba14eb9dbe373699417a2984eb559854bf5dbb 100644 (file)
@@ -160,7 +160,7 @@ void
 xlog_trace_iclog(xlog_in_core_t *iclog, uint state)
 {
        if (!iclog->ic_trace)
-               iclog->ic_trace = ktrace_alloc(256, KM_SLEEP);
+               iclog->ic_trace = ktrace_alloc(256, KM_NOFS);
        ktrace_enter(iclog->ic_trace,
                     (void *)((unsigned long)state),
                     (void *)((unsigned long)current_pid()),
@@ -336,15 +336,12 @@ xfs_log_done(xfs_mount_t  *mp,
        } else {
                xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)");
                xlog_regrant_reserve_log_space(log, ticket);
-       }
-
-       /* If this ticket was a permanent reservation and we aren't
-        * trying to release it, reset the inited flags; so next time
-        * we write, a start record will be written out.
-        */
-       if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) &&
-           (flags & XFS_LOG_REL_PERM_RESERV) == 0)
+               /* If this ticket was a permanent reservation and we aren't
+                * trying to release it, reset the inited flags; so next time
+                * we write, a start record will be written out.
+                */
                ticket->t_flags |= XLOG_TIC_INITED;
+       }
 
        return lsn;
 }      /* xfs_log_done */
@@ -357,11 +354,11 @@ xfs_log_done(xfs_mount_t  *mp,
  * Asynchronous forces are implemented by setting the WANT_SYNC
  * bit in the appropriate in-core log and then returning.
  *
- * Synchronous forces are implemented with a semaphore.  All callers
- * to force a given lsn to disk will wait on a semaphore attached to the
+ * Synchronous forces are implemented with a signal variable. All callers
+ * to force a given lsn to disk will wait on a the sv attached to the
  * specific in-core log.  When given in-core log finally completes its
  * write to disk, that thread will wake up all threads waiting on the
- * semaphore.
+ * sv.
  */
 int
 _xfs_log_force(
@@ -588,12 +585,12 @@ error:
  * mp          - ubiquitous xfs mount point structure
  */
 int
-xfs_log_mount_finish(xfs_mount_t *mp, int mfsi_flags)
+xfs_log_mount_finish(xfs_mount_t *mp)
 {
        int     error;
 
        if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
-               error = xlog_recover_finish(mp->m_log, mfsi_flags);
+               error = xlog_recover_finish(mp->m_log);
        else {
                error = 0;
                ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
@@ -707,7 +704,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
                if (!(iclog->ic_state == XLOG_STATE_ACTIVE ||
                      iclog->ic_state == XLOG_STATE_DIRTY)) {
                        if (!XLOG_FORCED_SHUTDOWN(log)) {
-                               sv_wait(&iclog->ic_forcesema, PMEM,
+                               sv_wait(&iclog->ic_force_wait, PMEM,
                                        &log->l_icloglock, s);
                        } else {
                                spin_unlock(&log->l_icloglock);
@@ -748,7 +745,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
                        || iclog->ic_state == XLOG_STATE_DIRTY
                        || iclog->ic_state == XLOG_STATE_IOERROR) ) {
 
-                               sv_wait(&iclog->ic_forcesema, PMEM,
+                               sv_wait(&iclog->ic_force_wait, PMEM,
                                        &log->l_icloglock, s);
                } else {
                        spin_unlock(&log->l_icloglock);
@@ -838,7 +835,7 @@ xfs_log_move_tail(xfs_mount_t       *mp,
                                break;
                        tail_lsn = 0;
                        free_bytes -= tic->t_unit_res;
-                       sv_signal(&tic->t_sema);
+                       sv_signal(&tic->t_wait);
                        tic = tic->t_next;
                } while (tic != log->l_write_headq);
        }
@@ -859,7 +856,7 @@ xfs_log_move_tail(xfs_mount_t       *mp,
                                break;
                        tail_lsn = 0;
                        free_bytes -= need_bytes;
-                       sv_signal(&tic->t_sema);
+                       sv_signal(&tic->t_wait);
                        tic = tic->t_next;
                } while (tic != log->l_reserve_headq);
        }
@@ -1285,8 +1282,8 @@ xlog_alloc_log(xfs_mount_t        *mp,
 
                ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp));
                ASSERT(XFS_BUF_VALUSEMA(iclog->ic_bp) <= 0);
-               sv_init(&iclog->ic_forcesema, SV_DEFAULT, "iclog-force");
-               sv_init(&iclog->ic_writesema, SV_DEFAULT, "iclog-write");
+               sv_init(&iclog->ic_force_wait, SV_DEFAULT, "iclog-force");
+               sv_init(&iclog->ic_write_wait, SV_DEFAULT, "iclog-write");
 
                iclogp = &iclog->ic_next;
        }
@@ -1565,8 +1562,8 @@ xlog_dealloc_log(xlog_t *log)
 
        iclog = log->l_iclog;
        for (i=0; i<log->l_iclog_bufs; i++) {
-               sv_destroy(&iclog->ic_forcesema);
-               sv_destroy(&iclog->ic_writesema);
+               sv_destroy(&iclog->ic_force_wait);
+               sv_destroy(&iclog->ic_write_wait);
                xfs_buf_free(iclog->ic_bp);
 #ifdef XFS_LOG_TRACE
                if (iclog->ic_trace != NULL) {
@@ -1976,7 +1973,7 @@ xlog_write(xfs_mount_t *  mp,
 /* Clean iclogs starting from the head.  This ordering must be
  * maintained, so an iclog doesn't become ACTIVE beyond one that
  * is SYNCING.  This is also required to maintain the notion that we use
- * a counting semaphore to hold off would be writers to the log when every
+ * a ordered wait queue to hold off would be writers to the log when every
  * iclog is trying to sync to disk.
  *
  * State Change: DIRTY -> ACTIVE
@@ -2240,7 +2237,7 @@ xlog_state_do_callback(
                        xlog_state_clean_log(log);
 
                        /* wake up threads waiting in xfs_log_force() */
-                       sv_broadcast(&iclog->ic_forcesema);
+                       sv_broadcast(&iclog->ic_force_wait);
 
                        iclog = iclog->ic_next;
                } while (first_iclog != iclog);
@@ -2302,8 +2299,7 @@ xlog_state_do_callback(
  * the second completion goes through.
  *
  * Callbacks could take time, so they are done outside the scope of the
- * global state machine log lock.  Assume that the calls to cvsema won't
- * take a long time.  At least we know it won't sleep.
+ * global state machine log lock.
  */
 STATIC void
 xlog_state_done_syncing(
@@ -2339,7 +2335,7 @@ xlog_state_done_syncing(
         * iclog buffer, we wake them all, one will get to do the
         * I/O, the others get to wait for the result.
         */
-       sv_broadcast(&iclog->ic_writesema);
+       sv_broadcast(&iclog->ic_write_wait);
        spin_unlock(&log->l_icloglock);
        xlog_state_do_callback(log, aborted, iclog);    /* also cleans log */
 }      /* xlog_state_done_syncing */
@@ -2347,11 +2343,9 @@ xlog_state_done_syncing(
 
 /*
  * If the head of the in-core log ring is not (ACTIVE or DIRTY), then we must
- * sleep.  The flush semaphore is set to the number of in-core buffers and
- * decremented around disk syncing.  Therefore, if all buffers are syncing,
- * this semaphore will cause new writes to sleep until a sync completes.
- * Otherwise, this code just does p() followed by v().  This approximates
- * a sleep/wakeup except we can't race.
+ * sleep.  We wait on the flush queue on the head iclog as that should be
+ * the first iclog to complete flushing. Hence if all iclogs are syncing,
+ * we will wait here and all new writes will sleep until a sync completes.
  *
  * The in-core logs are used in a circular fashion. They are not used
  * out-of-order even when an iclog past the head is free.
@@ -2508,7 +2502,7 @@ xlog_grant_log_space(xlog_t          *log,
                        goto error_return;
 
                XFS_STATS_INC(xs_sleep_logspace);
-               sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
+               sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s);
                /*
                 * If we got an error, and the filesystem is shutting down,
                 * we'll catch it down below. So just continue...
@@ -2534,7 +2528,7 @@ redo:
                xlog_trace_loggrant(log, tic,
                                    "xlog_grant_log_space: sleep 2");
                XFS_STATS_INC(xs_sleep_logspace);
-               sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
+               sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s);
 
                if (XLOG_FORCED_SHUTDOWN(log)) {
                        spin_lock(&log->l_grant_lock);
@@ -2633,7 +2627,7 @@ xlog_regrant_write_log_space(xlog_t          *log,
                        if (free_bytes < ntic->t_unit_res)
                                break;
                        free_bytes -= ntic->t_unit_res;
-                       sv_signal(&ntic->t_sema);
+                       sv_signal(&ntic->t_wait);
                        ntic = ntic->t_next;
                } while (ntic != log->l_write_headq);
 
@@ -2644,7 +2638,7 @@ xlog_regrant_write_log_space(xlog_t          *log,
                        xlog_trace_loggrant(log, tic,
                                    "xlog_regrant_write_log_space: sleep 1");
                        XFS_STATS_INC(xs_sleep_logspace);
-                       sv_wait(&tic->t_sema, PINOD|PLTWAIT,
+                       sv_wait(&tic->t_wait, PINOD|PLTWAIT,
                                &log->l_grant_lock, s);
 
                        /* If we're shutting down, this tic is already
@@ -2673,7 +2667,7 @@ redo:
                if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
                        xlog_ins_ticketq(&log->l_write_headq, tic);
                XFS_STATS_INC(xs_sleep_logspace);
-               sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
+               sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s);
 
                /* If we're shutting down, this tic is already off the queue */
                if (XLOG_FORCED_SHUTDOWN(log)) {
@@ -2916,7 +2910,7 @@ xlog_state_switch_iclogs(xlog_t           *log,
  *     2. the current iclog is drity, and the previous iclog is in the
  *             active or dirty state.
  *
- * We may sleep (call psema) if:
+ * We may sleep if:
  *
  *     1. the current iclog is not in the active nor dirty state.
  *     2. the current iclog dirty, and the previous iclog is not in the
@@ -3013,7 +3007,7 @@ maybe_sleep:
                        return XFS_ERROR(EIO);
                }
                XFS_STATS_INC(xs_log_force_sleep);
-               sv_wait(&iclog->ic_forcesema, PINOD, &log->l_icloglock, s);
+               sv_wait(&iclog->ic_force_wait, PINOD, &log->l_icloglock, s);
                /*
                 * No need to grab the log lock here since we're
                 * only deciding whether or not to return EIO
@@ -3096,7 +3090,7 @@ try_again:
                                                 XLOG_STATE_SYNCING))) {
                        ASSERT(!(iclog->ic_state & XLOG_STATE_IOERROR));
                        XFS_STATS_INC(xs_log_force_sleep);
-                       sv_wait(&iclog->ic_prev->ic_writesema, PSWP,
+                       sv_wait(&iclog->ic_prev->ic_write_wait, PSWP,
                                &log->l_icloglock, s);
                        *log_flushed = 1;
                        already_slept = 1;
@@ -3116,7 +3110,7 @@ try_again:
            !(iclog->ic_state & (XLOG_STATE_ACTIVE | XLOG_STATE_DIRTY))) {
 
                /*
-                * Don't wait on the forcesema if we know that we've
+                * Don't wait on completion if we know that we've
                 * gotten a log write error.
                 */
                if (iclog->ic_state & XLOG_STATE_IOERROR) {
@@ -3124,7 +3118,7 @@ try_again:
                        return XFS_ERROR(EIO);
                }
                XFS_STATS_INC(xs_log_force_sleep);
-               sv_wait(&iclog->ic_forcesema, PSWP, &log->l_icloglock, s);
+               sv_wait(&iclog->ic_force_wait, PSWP, &log->l_icloglock, s);
                /*
                 * No need to grab the log lock here since we're
                 * only deciding whether or not to return EIO
@@ -3180,7 +3174,7 @@ STATIC void
 xlog_ticket_put(xlog_t         *log,
                xlog_ticket_t   *ticket)
 {
-       sv_destroy(&ticket->t_sema);
+       sv_destroy(&ticket->t_wait);
        kmem_zone_free(xfs_log_ticket_zone, ticket);
 }      /* xlog_ticket_put */
 
@@ -3270,7 +3264,7 @@ xlog_ticket_get(xlog_t            *log,
        tic->t_trans_type       = 0;
        if (xflags & XFS_LOG_PERM_RESERV)
                tic->t_flags |= XLOG_TIC_PERM_RESERV;
-       sv_init(&(tic->t_sema), SV_DEFAULT, "logtick");
+       sv_init(&(tic->t_wait), SV_DEFAULT, "logtick");
 
        xlog_tic_reset_res(tic);
 
@@ -3557,14 +3551,14 @@ xfs_log_force_umount(
         */
        if ((tic = log->l_reserve_headq)) {
                do {
-                       sv_signal(&tic->t_sema);
+                       sv_signal(&tic->t_wait);
                        tic = tic->t_next;
                } while (tic != log->l_reserve_headq);
        }
 
        if ((tic = log->l_write_headq)) {
                do {
-                       sv_signal(&tic->t_sema);
+                       sv_signal(&tic->t_wait);
                        tic = tic->t_next;
                } while (tic != log->l_write_headq);
        }
index d1d678ecb63e4b89cacdfb38acfb853ef8f79c59..d47b91f10822b98400a6d11961a8a12d4e930d76 100644 (file)
@@ -149,7 +149,7 @@ int   xfs_log_mount(struct xfs_mount        *mp,
                        struct xfs_buftarg      *log_target,
                        xfs_daddr_t             start_block,
                        int                     num_bblocks);
-int      xfs_log_mount_finish(struct xfs_mount *mp, int);
+int      xfs_log_mount_finish(struct xfs_mount *mp);
 void     xfs_log_move_tail(struct xfs_mount    *mp,
                            xfs_lsn_t           tail_lsn);
 int      xfs_log_notify(struct xfs_mount       *mp,
index 6245913196b4ec483f5488b2b6525a555ec6734b..c8a5b22ee3e3b02fa1cd13e639bf2fe9b3f525a7 100644 (file)
@@ -241,7 +241,7 @@ typedef struct xlog_res {
 } xlog_res_t;
 
 typedef struct xlog_ticket {
-       sv_t               t_sema;       /* sleep on this semaphore      : 20 */
+       sv_t               t_wait;       /* ticket wait queue            : 20 */
        struct xlog_ticket *t_next;      /*                              :4|8 */
        struct xlog_ticket *t_prev;      /*                              :4|8 */
        xlog_tid_t         t_tid;        /* transaction identifier       : 4  */
@@ -314,7 +314,7 @@ typedef struct xlog_rec_ext_header {
  *     xlog_rec_header_t into the reserved space.
  * - ic_data follows, so a write to disk can start at the beginning of
  *     the iclog.
- * - ic_forcesema is used to implement synchronous forcing of the iclog to disk.
+ * - ic_forcewait is used to implement synchronous forcing of the iclog to disk.
  * - ic_next is the pointer to the next iclog in the ring.
  * - ic_bp is a pointer to the buffer used to write this incore log to disk.
  * - ic_log is a pointer back to the global log structure.
@@ -339,8 +339,8 @@ typedef struct xlog_rec_ext_header {
  * and move everything else out to subsequent cachelines.
  */
 typedef struct xlog_iclog_fields {
-       sv_t                    ic_forcesema;
-       sv_t                    ic_writesema;
+       sv_t                    ic_force_wait;
+       sv_t                    ic_write_wait;
        struct xlog_in_core     *ic_next;
        struct xlog_in_core     *ic_prev;
        struct xfs_buf          *ic_bp;
@@ -377,8 +377,8 @@ typedef struct xlog_in_core {
 /*
  * Defines to save our code from this glop.
  */
-#define        ic_forcesema    hic_fields.ic_forcesema
-#define ic_writesema   hic_fields.ic_writesema
+#define        ic_force_wait   hic_fields.ic_force_wait
+#define ic_write_wait  hic_fields.ic_write_wait
 #define        ic_next         hic_fields.ic_next
 #define        ic_prev         hic_fields.ic_prev
 #define        ic_bp           hic_fields.ic_bp
@@ -468,7 +468,7 @@ extern int   xlog_find_tail(xlog_t  *log,
                                xfs_daddr_t *head_blk,
                                xfs_daddr_t *tail_blk);
 extern int      xlog_recover(xlog_t *log);
-extern int      xlog_recover_finish(xlog_t *log, int mfsi_flags);
+extern int      xlog_recover_finish(xlog_t *log);
 extern void     xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int);
 extern void     xlog_recover_process_iunlinks(xlog_t *log);
 
index 9eb722ec744e528bd4aa5a8a76ce473ef35bd3f4..82d46ce69d5f1e49b73f1842f92e06731af599fb 100644 (file)
@@ -3940,8 +3940,7 @@ xlog_recover(
  */
 int
 xlog_recover_finish(
-       xlog_t          *log,
-       int             mfsi_flags)
+       xlog_t          *log)
 {
        /*
         * Now we're ready to do the transactions needed for the
@@ -3969,9 +3968,7 @@ xlog_recover_finish(
                xfs_log_force(log->l_mp, (xfs_lsn_t)0,
                              (XFS_LOG_FORCE | XFS_LOG_SYNC));
 
-               if ( (mfsi_flags & XFS_MFSI_NOUNLINK) == 0 ) {
-                       xlog_recover_process_iunlinks(log);
-               }
+               xlog_recover_process_iunlinks(log);
 
                xlog_recover_check_summary(log);
 
index 6c5d1325e7f65661ce35a765badac586b474fd01..a4503f5e9497714a62e4fdc6cf90ac718cc5a065 100644 (file)
@@ -128,7 +128,7 @@ static const struct {
  * initialized.
  */
 STATIC void
-xfs_mount_free(
+xfs_free_perag(
        xfs_mount_t     *mp)
 {
        if (mp->m_perag) {
@@ -139,20 +139,6 @@ xfs_mount_free(
                                kmem_free(mp->m_perag[agno].pagb_list);
                kmem_free(mp->m_perag);
        }
-
-       spinlock_destroy(&mp->m_ail_lock);
-       spinlock_destroy(&mp->m_sb_lock);
-       mutex_destroy(&mp->m_ilock);
-       mutex_destroy(&mp->m_growlock);
-       if (mp->m_quotainfo)
-               XFS_QM_DONE(mp);
-
-       if (mp->m_fsname != NULL)
-               kmem_free(mp->m_fsname);
-       if (mp->m_rtname != NULL)
-               kmem_free(mp->m_rtname);
-       if (mp->m_logname != NULL)
-               kmem_free(mp->m_logname);
 }
 
 /*
@@ -704,11 +690,11 @@ xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
  * Update alignment values based on mount options and sb values
  */
 STATIC int
-xfs_update_alignment(xfs_mount_t *mp, int mfsi_flags, __uint64_t *update_flags)
+xfs_update_alignment(xfs_mount_t *mp, __uint64_t *update_flags)
 {
        xfs_sb_t        *sbp = &(mp->m_sb);
 
-       if (mp->m_dalign && !(mfsi_flags & XFS_MFSI_SECOND)) {
+       if (mp->m_dalign) {
                /*
                 * If stripe unit and stripe width are not multiples
                 * of the fs blocksize turn off alignment.
@@ -864,7 +850,7 @@ xfs_set_inoalignment(xfs_mount_t *mp)
  * Check that the data (and log if separate) are an ok size.
  */
 STATIC int
-xfs_check_sizes(xfs_mount_t *mp, int mfsi_flags)
+xfs_check_sizes(xfs_mount_t *mp)
 {
        xfs_buf_t       *bp;
        xfs_daddr_t     d;
@@ -887,8 +873,7 @@ xfs_check_sizes(xfs_mount_t *mp, int mfsi_flags)
                return error;
        }
 
-       if (((mfsi_flags & XFS_MFSI_CLIENT) == 0) &&
-           mp->m_logdev_targp != mp->m_ddev_targp) {
+       if (mp->m_logdev_targp != mp->m_ddev_targp) {
                d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
                if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
                        cmn_err(CE_WARN, "XFS: size check 3 failed");
@@ -923,15 +908,13 @@ xfs_check_sizes(xfs_mount_t *mp, int mfsi_flags)
  */
 int
 xfs_mountfs(
-       xfs_mount_t     *mp,
-       int             mfsi_flags)
+       xfs_mount_t     *mp)
 {
        xfs_sb_t        *sbp = &(mp->m_sb);
        xfs_inode_t     *rip;
        __uint64_t      resblks;
        __int64_t       update_flags = 0LL;
        uint            quotamount, quotaflags;
-       int             agno;
        int             uuid_mounted = 0;
        int             error = 0;
 
@@ -985,7 +968,7 @@ xfs_mountfs(
         * allocator alignment is within an ag, therefore ag has
         * to be aligned at stripe boundary.
         */
-       error = xfs_update_alignment(mp, mfsi_flags, &update_flags);
+       error = xfs_update_alignment(mp, &update_flags);
        if (error)
                goto error1;
 
@@ -1004,8 +987,7 @@ xfs_mountfs(
         * since a single partition filesystem is identical to a single
         * partition volume/filesystem.
         */
-       if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
-           (mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
+       if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
                if (xfs_uuid_mount(mp)) {
                        error = XFS_ERROR(EINVAL);
                        goto error1;
@@ -1033,7 +1015,7 @@ xfs_mountfs(
        /*
         * Check that the data (and log if separate) are an ok size.
         */
-       error = xfs_check_sizes(mp, mfsi_flags);
+       error = xfs_check_sizes(mp);
        if (error)
                goto error1;
 
@@ -1046,13 +1028,6 @@ xfs_mountfs(
                goto error1;
        }
 
-       /*
-        * For client case we are done now
-        */
-       if (mfsi_flags & XFS_MFSI_CLIENT) {
-               return 0;
-       }
-
        /*
         *  Copies the low order bits of the timestamp and the randomly
         *  set "sequence" number out of a UUID.
@@ -1077,8 +1052,10 @@ xfs_mountfs(
         * Allocate and initialize the per-ag data.
         */
        init_rwsem(&mp->m_peraglock);
-       mp->m_perag =
-               kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP);
+       mp->m_perag = kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t),
+                                 KM_MAYFAIL);
+       if (!mp->m_perag)
+               goto error1;
 
        mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount);
 
@@ -1190,7 +1167,7 @@ xfs_mountfs(
         * delayed until after the root and real-time bitmap inodes
         * were consistently read in.
         */
-       error = xfs_log_mount_finish(mp, mfsi_flags);
+       error = xfs_log_mount_finish(mp);
        if (error) {
                cmn_err(CE_WARN, "XFS: log mount finish failed");
                goto error4;
@@ -1199,7 +1176,7 @@ xfs_mountfs(
        /*
         * Complete the quota initialisation, post-log-replay component.
         */
-       error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags);
+       error = XFS_QM_MOUNT(mp, quotamount, quotaflags);
        if (error)
                goto error4;
 
@@ -1233,12 +1210,7 @@ xfs_mountfs(
  error3:
        xfs_log_unmount_dealloc(mp);
  error2:
-       for (agno = 0; agno < sbp->sb_agcount; agno++)
-               if (mp->m_perag[agno].pagb_list)
-                       kmem_free(mp->m_perag[agno].pagb_list);
-       kmem_free(mp->m_perag);
-       mp->m_perag = NULL;
-       /* FALLTHROUGH */
+       xfs_free_perag(mp);
  error1:
        if (uuid_mounted)
                uuid_table_remove(&mp->m_sb.sb_uuid);
@@ -1246,16 +1218,17 @@ xfs_mountfs(
 }
 
 /*
- * xfs_unmountfs
- *
  * This flushes out the inodes,dquots and the superblock, unmounts the
  * log and makes sure that incore structures are freed.
  */
-int
-xfs_unmountfs(xfs_mount_t *mp)
+void
+xfs_unmountfs(
+       struct xfs_mount        *mp)
 {
-       __uint64_t      resblks;
-       int             error = 0;
+       __uint64_t              resblks;
+       int                     error;
+
+       IRELE(mp->m_rootip);
 
        /*
         * We can potentially deadlock here if we have an inode cluster
@@ -1312,8 +1285,6 @@ xfs_unmountfs(xfs_mount_t *mp)
        xfs_unmountfs_wait(mp);                 /* wait for async bufs */
        xfs_log_unmount(mp);                    /* Done! No more fs ops. */
 
-       xfs_freesb(mp);
-
        /*
         * All inodes from this mount point should be freed.
         */
@@ -1322,11 +1293,12 @@ xfs_unmountfs(xfs_mount_t *mp)
        if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0)
                uuid_table_remove(&mp->m_sb.sb_uuid);
 
-#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
+#if defined(DEBUG)
        xfs_errortag_clearall(mp, 0);
 #endif
-       xfs_mount_free(mp);
-       return 0;
+       xfs_free_perag(mp);
+       if (mp->m_quotainfo)
+               XFS_QM_DONE(mp);
 }
 
 STATIC void
index 5269bd6e3df08ffa624ccf8c1e691ccd0622c33c..f3c1024b1241ed8663568db7e309e75c83f866f0 100644 (file)
@@ -114,7 +114,7 @@ struct xfs_dqtrxops;
 struct xfs_quotainfo;
 
 typedef int    (*xfs_qminit_t)(struct xfs_mount *, uint *, uint *);
-typedef int    (*xfs_qmmount_t)(struct xfs_mount *, uint, uint, int);
+typedef int    (*xfs_qmmount_t)(struct xfs_mount *, uint, uint);
 typedef int    (*xfs_qmunmount_t)(struct xfs_mount *);
 typedef void   (*xfs_qmdone_t)(struct xfs_mount *);
 typedef void   (*xfs_dqrele_t)(struct xfs_dquot *);
@@ -158,8 +158,8 @@ typedef struct xfs_qmops {
 
 #define XFS_QM_INIT(mp, mnt, fl) \
        (*(mp)->m_qm_ops->xfs_qminit)(mp, mnt, fl)
-#define XFS_QM_MOUNT(mp, mnt, fl, mfsi_flags) \
-       (*(mp)->m_qm_ops->xfs_qmmount)(mp, mnt, fl, mfsi_flags)
+#define XFS_QM_MOUNT(mp, mnt, fl) \
+       (*(mp)->m_qm_ops->xfs_qmmount)(mp, mnt, fl)
 #define XFS_QM_UNMOUNT(mp) \
        (*(mp)->m_qm_ops->xfs_qmunmount)(mp)
 #define XFS_QM_DONE(mp) \
@@ -442,13 +442,6 @@ void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,
 /*
  * Flags for xfs_mountfs
  */
-#define XFS_MFSI_SECOND                0x01    /* Secondary mount -- skip stuff */
-#define XFS_MFSI_CLIENT                0x02    /* Is a client -- skip lots of stuff */
-/*     XFS_MFSI_RRINODES       */
-#define XFS_MFSI_NOUNLINK      0x08    /* Skip unlinked inode processing in */
-                                       /* log recovery */
-#define XFS_MFSI_NO_QUOTACHECK 0x10    /* Skip quotacheck processing */
-/*     XFS_MFSI_CONVERT_SUNIT  */
 #define XFS_MFSI_QUIET         0x40    /* Be silent if mount errors found */
 
 #define XFS_DADDR_TO_AGNO(mp,d)         xfs_daddr_to_agno(mp,d)
@@ -517,10 +510,10 @@ typedef struct xfs_mod_sb {
 
 extern void    xfs_mod_sb(xfs_trans_t *, __int64_t);
 extern int     xfs_log_sbcount(xfs_mount_t *, uint);
-extern int     xfs_mountfs(xfs_mount_t *mp, int);
+extern int     xfs_mountfs(xfs_mount_t *mp);
 extern void    xfs_mountfs_check_barriers(xfs_mount_t *mp);
 
-extern int     xfs_unmountfs(xfs_mount_t *);
+extern void    xfs_unmountfs(xfs_mount_t *);
 extern int     xfs_unmountfs_writesb(xfs_mount_t *);
 extern int     xfs_unmount_flush(xfs_mount_t *, int);
 extern int     xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
index bf87a5913504382a07b121ca119c0187bbeb7473..e2f68de161599d28d7b33f3348fd6dea4680f5e7 100644 (file)
@@ -73,18 +73,6 @@ STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int,
  * Internal functions.
  */
 
-/*
- * xfs_lowbit32: get low bit set out of 32-bit argument, -1 if none set.
- */
-STATIC int
-xfs_lowbit32(
-       __uint32_t      v)
-{
-       if (v)
-               return ffs(v) - 1;
-       return -1;
-}
-
 /*
  * Allocate space to the bitmap or summary file, and zero it, for growfs.
  */
@@ -450,6 +438,7 @@ xfs_rtallocate_extent_near(
        }
        bbno = XFS_BITTOBLOCK(mp, bno);
        i = 0;
+       ASSERT(minlen != 0);
        log2len = xfs_highbit32(minlen);
        /*
         * Loop over all bitmap blocks (bbno + i is current block).
@@ -618,6 +607,8 @@ xfs_rtallocate_extent_size(
        xfs_suminfo_t   sum;            /* summary information for extents */
 
        ASSERT(minlen % prod == 0 && maxlen % prod == 0);
+       ASSERT(maxlen != 0);
+
        /*
         * Loop over all the levels starting with maxlen.
         * At each level, look at all the bitmap blocks, to see if there
@@ -675,6 +666,9 @@ xfs_rtallocate_extent_size(
                *rtblock = NULLRTBLOCK;
                return 0;
        }
+       ASSERT(minlen != 0);
+       ASSERT(maxlen != 0);
+
        /*
         * Loop over sizes, from maxlen down to minlen.
         * This time, when we do the allocations, allow smaller ones
@@ -1961,6 +1955,7 @@ xfs_growfs_rt(
                                  nsbp->sb_blocksize * nsbp->sb_rextsize);
                nsbp->sb_rextents = nsbp->sb_rblocks;
                do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
+               ASSERT(nsbp->sb_rextents != 0);
                nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
                nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
                nrsumsize =
index b0f31c09a76d31f39bde2b1089f39d48423329d6..3a82576dde9a39659f239adae1d42da66ed26b01 100644 (file)
@@ -314,7 +314,7 @@ xfs_bioerror_relse(
                 * ASYNC buffers.
                 */
                XFS_BUF_ERROR(bp, EIO);
-               XFS_BUF_V_IODONESEMA(bp);
+               XFS_BUF_FINISH_IOWAIT(bp);
        } else {
                xfs_buf_relse(bp);
        }
index e4ebddd3c500bd577c29fecbfd233efa6a890f5f..4e1c22a23be5fb2496b20600767de4ee1a8822ce 100644 (file)
@@ -43,6 +43,7 @@
 #include "xfs_quota.h"
 #include "xfs_trans_priv.h"
 #include "xfs_trans_space.h"
+#include "xfs_inode_item.h"
 
 
 STATIC void    xfs_trans_apply_sb_deltas(xfs_trans_t *);
@@ -253,7 +254,7 @@ _xfs_trans_alloc(
        tp->t_mountp = mp;
        tp->t_items_free = XFS_LIC_NUM_SLOTS;
        tp->t_busy_free = XFS_LBC_NUM_SLOTS;
-       XFS_LIC_INIT(&(tp->t_items));
+       xfs_lic_init(&(tp->t_items));
        XFS_LBC_INIT(&(tp->t_busy));
        return tp;
 }
@@ -282,7 +283,7 @@ xfs_trans_dup(
        ntp->t_mountp = tp->t_mountp;
        ntp->t_items_free = XFS_LIC_NUM_SLOTS;
        ntp->t_busy_free = XFS_LBC_NUM_SLOTS;
-       XFS_LIC_INIT(&(ntp->t_items));
+       xfs_lic_init(&(ntp->t_items));
        XFS_LBC_INIT(&(ntp->t_busy));
 
        ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
@@ -1169,7 +1170,7 @@ xfs_trans_cancel(
                while (licp != NULL) {
                        lidp = licp->lic_descs;
                        for (i = 0; i < licp->lic_unused; i++, lidp++) {
-                               if (XFS_LIC_ISFREE(licp, i)) {
+                               if (xfs_lic_isfree(licp, i)) {
                                        continue;
                                }
 
@@ -1216,6 +1217,68 @@ xfs_trans_free(
        kmem_zone_free(xfs_trans_zone, tp);
 }
 
+/*
+ * Roll from one trans in the sequence of PERMANENT transactions to
+ * the next: permanent transactions are only flushed out when
+ * committed with XFS_TRANS_RELEASE_LOG_RES, but we still want as soon
+ * as possible to let chunks of it go to the log. So we commit the
+ * chunk we've been working on and get a new transaction to continue.
+ */
+int
+xfs_trans_roll(
+       struct xfs_trans        **tpp,
+       struct xfs_inode        *dp)
+{
+       struct xfs_trans        *trans;
+       unsigned int            logres, count;
+       int                     error;
+
+       /*
+        * Ensure that the inode is always logged.
+        */
+       trans = *tpp;
+       xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
+
+       /*
+        * Copy the critical parameters from one trans to the next.
+        */
+       logres = trans->t_log_res;
+       count = trans->t_log_count;
+       *tpp = xfs_trans_dup(trans);
+
+       /*
+        * Commit the current transaction.
+        * If this commit failed, then it'd just unlock those items that
+        * are not marked ihold. That also means that a filesystem shutdown
+        * is in progress. The caller takes the responsibility to cancel
+        * the duplicate transaction that gets returned.
+        */
+       error = xfs_trans_commit(trans, 0);
+       if (error)
+               return (error);
+
+       trans = *tpp;
+
+       /*
+        * Reserve space in the log for th next transaction.
+        * This also pushes items in the "AIL", the list of logged items,
+        * out to disk if they are taking up space at the tail of the log
+        * that we want to use.  This requires that either nothing be locked
+        * across this call, or that anything that is locked be logged in
+        * the prior and the next transactions.
+        */
+       error = xfs_trans_reserve(trans, 0, logres, 0,
+                                 XFS_TRANS_PERM_LOG_RES, count);
+       /*
+        *  Ensure that the inode is in the new transaction and locked.
+        */
+       if (error)
+               return error;
+
+       xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL);
+       xfs_trans_ihold(trans, dp);
+       return 0;
+}
 
 /*
  * THIS SHOULD BE REWRITTEN TO USE xfs_trans_next_item().
@@ -1253,7 +1316,7 @@ xfs_trans_committed(
         * Special case the chunk embedded in the transaction.
         */
        licp = &(tp->t_items);
-       if (!(XFS_LIC_ARE_ALL_FREE(licp))) {
+       if (!(xfs_lic_are_all_free(licp))) {
                xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag);
        }
 
@@ -1262,7 +1325,7 @@ xfs_trans_committed(
         */
        licp = licp->lic_next;
        while (licp != NULL) {
-               ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
+               ASSERT(!xfs_lic_are_all_free(licp));
                xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag);
                next_licp = licp->lic_next;
                kmem_free(licp);
@@ -1325,7 +1388,7 @@ xfs_trans_chunk_committed(
 
        lidp = licp->lic_descs;
        for (i = 0; i < licp->lic_unused; i++, lidp++) {
-               if (XFS_LIC_ISFREE(licp, i)) {
+               if (xfs_lic_isfree(licp, i)) {
                        continue;
                }
 
index 0804207c7391f8405aa2847b3ba7d66353dc9489..74c80bd2b0ec5a838e325945b9787a2a9c3c10b3 100644 (file)
@@ -210,62 +210,52 @@ typedef struct xfs_log_item_chunk {
  * lic_unused to the right value (0 matches all free).  The
  * lic_descs.lid_index values are set up as each desc is allocated.
  */
-#define        XFS_LIC_INIT(cp)        xfs_lic_init(cp)
 static inline void xfs_lic_init(xfs_log_item_chunk_t *cp)
 {
        cp->lic_free = XFS_LIC_FREEMASK;
 }
 
-#define        XFS_LIC_INIT_SLOT(cp,slot)      xfs_lic_init_slot(cp, slot)
 static inline void xfs_lic_init_slot(xfs_log_item_chunk_t *cp, int slot)
 {
        cp->lic_descs[slot].lid_index = (unsigned char)(slot);
 }
 
-#define        XFS_LIC_VACANCY(cp)             xfs_lic_vacancy(cp)
 static inline int xfs_lic_vacancy(xfs_log_item_chunk_t *cp)
 {
        return cp->lic_free & XFS_LIC_FREEMASK;
 }
 
-#define        XFS_LIC_ALL_FREE(cp)            xfs_lic_all_free(cp)
 static inline void xfs_lic_all_free(xfs_log_item_chunk_t *cp)
 {
        cp->lic_free = XFS_LIC_FREEMASK;
 }
 
-#define        XFS_LIC_ARE_ALL_FREE(cp)        xfs_lic_are_all_free(cp)
 static inline int xfs_lic_are_all_free(xfs_log_item_chunk_t *cp)
 {
        return ((cp->lic_free & XFS_LIC_FREEMASK) == XFS_LIC_FREEMASK);
 }
 
-#define        XFS_LIC_ISFREE(cp,slot) xfs_lic_isfree(cp,slot)
 static inline int xfs_lic_isfree(xfs_log_item_chunk_t *cp, int slot)
 {
        return (cp->lic_free & (1 << slot));
 }
 
-#define        XFS_LIC_CLAIM(cp,slot)          xfs_lic_claim(cp,slot)
 static inline void xfs_lic_claim(xfs_log_item_chunk_t *cp, int slot)
 {
        cp->lic_free &= ~(1 << slot);
 }
 
-#define        XFS_LIC_RELSE(cp,slot)          xfs_lic_relse(cp,slot)
 static inline void xfs_lic_relse(xfs_log_item_chunk_t *cp, int slot)
 {
        cp->lic_free |= 1 << slot;
 }
 
-#define        XFS_LIC_SLOT(cp,slot)           xfs_lic_slot(cp,slot)
 static inline xfs_log_item_desc_t *
 xfs_lic_slot(xfs_log_item_chunk_t *cp, int slot)
 {
        return &(cp->lic_descs[slot]);
 }
 
-#define        XFS_LIC_DESC_TO_SLOT(dp)        xfs_lic_desc_to_slot(dp)
 static inline int xfs_lic_desc_to_slot(xfs_log_item_desc_t *dp)
 {
        return (uint)dp->lid_index;
@@ -278,7 +268,6 @@ static inline int xfs_lic_desc_to_slot(xfs_log_item_desc_t *dp)
  * All of this yields the address of the chunk, which is
  * cast to a chunk pointer.
  */
-#define        XFS_LIC_DESC_TO_CHUNK(dp)       xfs_lic_desc_to_chunk(dp)
 static inline xfs_log_item_chunk_t *
 xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
 {
@@ -986,6 +975,7 @@ int         _xfs_trans_commit(xfs_trans_t *,
                                  int *);
 #define xfs_trans_commit(tp, flags)    _xfs_trans_commit(tp, flags, NULL)
 void           xfs_trans_cancel(xfs_trans_t *, int);
+int            xfs_trans_roll(struct xfs_trans **, struct xfs_inode *);
 int            xfs_trans_ail_init(struct xfs_mount *);
 void           xfs_trans_ail_destroy(struct xfs_mount *);
 void           xfs_trans_push_ail(struct xfs_mount *, xfs_lsn_t);
index cb0c5839154bf8017c86d52251993c3d1ac75f18..4e855b5ced666eefeb5b910e0599adeed3a0ec17 100644 (file)
@@ -1021,16 +1021,16 @@ xfs_trans_buf_item_match(
        bp = NULL;
        len = BBTOB(len);
        licp = &tp->t_items;
-       if (!XFS_LIC_ARE_ALL_FREE(licp)) {
+       if (!xfs_lic_are_all_free(licp)) {
                for (i = 0; i < licp->lic_unused; i++) {
                        /*
                         * Skip unoccupied slots.
                         */
-                       if (XFS_LIC_ISFREE(licp, i)) {
+                       if (xfs_lic_isfree(licp, i)) {
                                continue;
                        }
 
-                       lidp = XFS_LIC_SLOT(licp, i);
+                       lidp = xfs_lic_slot(licp, i);
                        blip = (xfs_buf_log_item_t *)lidp->lid_item;
                        if (blip->bli_item.li_type != XFS_LI_BUF) {
                                continue;
@@ -1074,7 +1074,7 @@ xfs_trans_buf_item_match_all(
        bp = NULL;
        len = BBTOB(len);
        for (licp = &tp->t_items; licp != NULL; licp = licp->lic_next) {
-               if (XFS_LIC_ARE_ALL_FREE(licp)) {
+               if (xfs_lic_are_all_free(licp)) {
                        ASSERT(licp == &tp->t_items);
                        ASSERT(licp->lic_next == NULL);
                        return NULL;
@@ -1083,11 +1083,11 @@ xfs_trans_buf_item_match_all(
                        /*
                         * Skip unoccupied slots.
                         */
-                       if (XFS_LIC_ISFREE(licp, i)) {
+                       if (xfs_lic_isfree(licp, i)) {
                                continue;
                        }
 
-                       lidp = XFS_LIC_SLOT(licp, i);
+                       lidp = xfs_lic_slot(licp, i);
                        blip = (xfs_buf_log_item_t *)lidp->lid_item;
                        if (blip->bli_item.li_type != XFS_LI_BUF) {
                                continue;
index db5c83595526442cae1f2890080525aecfdbf33b..3c666e8317f82bd3f0e41451a06bd39d3c9ff8db 100644 (file)
@@ -53,11 +53,11 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip)
                 * Initialize the chunk, and then
                 * claim the first slot in the newly allocated chunk.
                 */
-               XFS_LIC_INIT(licp);
-               XFS_LIC_CLAIM(licp, 0);
+               xfs_lic_init(licp);
+               xfs_lic_claim(licp, 0);
                licp->lic_unused = 1;
-               XFS_LIC_INIT_SLOT(licp, 0);
-               lidp = XFS_LIC_SLOT(licp, 0);
+               xfs_lic_init_slot(licp, 0);
+               lidp = xfs_lic_slot(licp, 0);
 
                /*
                 * Link in the new chunk and update the free count.
@@ -88,14 +88,14 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip)
         */
        licp = &tp->t_items;
        while (licp != NULL) {
-               if (XFS_LIC_VACANCY(licp)) {
+               if (xfs_lic_vacancy(licp)) {
                        if (licp->lic_unused <= XFS_LIC_MAX_SLOT) {
                                i = licp->lic_unused;
-                               ASSERT(XFS_LIC_ISFREE(licp, i));
+                               ASSERT(xfs_lic_isfree(licp, i));
                                break;
                        }
                        for (i = 0; i <= XFS_LIC_MAX_SLOT; i++) {
-                               if (XFS_LIC_ISFREE(licp, i))
+                               if (xfs_lic_isfree(licp, i))
                                        break;
                        }
                        ASSERT(i <= XFS_LIC_MAX_SLOT);
@@ -108,12 +108,12 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip)
         * If we find a free descriptor, claim it,
         * initialize it, and return it.
         */
-       XFS_LIC_CLAIM(licp, i);
+       xfs_lic_claim(licp, i);
        if (licp->lic_unused <= i) {
                licp->lic_unused = i + 1;
-               XFS_LIC_INIT_SLOT(licp, i);
+               xfs_lic_init_slot(licp, i);
        }
-       lidp = XFS_LIC_SLOT(licp, i);
+       lidp = xfs_lic_slot(licp, i);
        tp->t_items_free--;
        lidp->lid_item = lip;
        lidp->lid_flags = 0;
@@ -136,9 +136,9 @@ xfs_trans_free_item(xfs_trans_t     *tp, xfs_log_item_desc_t *lidp)
        xfs_log_item_chunk_t    *licp;
        xfs_log_item_chunk_t    **licpp;
 
-       slot = XFS_LIC_DESC_TO_SLOT(lidp);
-       licp = XFS_LIC_DESC_TO_CHUNK(lidp);
-       XFS_LIC_RELSE(licp, slot);
+       slot = xfs_lic_desc_to_slot(lidp);
+       licp = xfs_lic_desc_to_chunk(lidp);
+       xfs_lic_relse(licp, slot);
        lidp->lid_item->li_desc = NULL;
        tp->t_items_free++;
 
@@ -154,7 +154,7 @@ xfs_trans_free_item(xfs_trans_t     *tp, xfs_log_item_desc_t *lidp)
         * Also decrement the transaction structure's count of free items
         * by the number in a chunk since we are freeing an empty chunk.
         */
-       if (XFS_LIC_ARE_ALL_FREE(licp) && (licp != &(tp->t_items))) {
+       if (xfs_lic_are_all_free(licp) && (licp != &(tp->t_items))) {
                licpp = &(tp->t_items.lic_next);
                while (*licpp != licp) {
                        ASSERT(*licpp != NULL);
@@ -207,20 +207,20 @@ xfs_trans_first_item(xfs_trans_t *tp)
        /*
         * If it's not in the first chunk, skip to the second.
         */
-       if (XFS_LIC_ARE_ALL_FREE(licp)) {
+       if (xfs_lic_are_all_free(licp)) {
                licp = licp->lic_next;
        }
 
        /*
         * Return the first non-free descriptor in the chunk.
         */
-       ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
+       ASSERT(!xfs_lic_are_all_free(licp));
        for (i = 0; i < licp->lic_unused; i++) {
-               if (XFS_LIC_ISFREE(licp, i)) {
+               if (xfs_lic_isfree(licp, i)) {
                        continue;
                }
 
-               return XFS_LIC_SLOT(licp, i);
+               return xfs_lic_slot(licp, i);
        }
        cmn_err(CE_WARN, "xfs_trans_first_item() -- no first item");
        return NULL;
@@ -242,18 +242,18 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
        xfs_log_item_chunk_t    *licp;
        int                     i;
 
-       licp = XFS_LIC_DESC_TO_CHUNK(lidp);
+       licp = xfs_lic_desc_to_chunk(lidp);
 
        /*
         * First search the rest of the chunk. The for loop keeps us
         * from referencing things beyond the end of the chunk.
         */
-       for (i = (int)XFS_LIC_DESC_TO_SLOT(lidp) + 1; i < licp->lic_unused; i++) {
-               if (XFS_LIC_ISFREE(licp, i)) {
+       for (i = (int)xfs_lic_desc_to_slot(lidp) + 1; i < licp->lic_unused; i++) {
+               if (xfs_lic_isfree(licp, i)) {
                        continue;
                }
 
-               return XFS_LIC_SLOT(licp, i);
+               return xfs_lic_slot(licp, i);
        }
 
        /*
@@ -266,13 +266,13 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
        }
 
        licp = licp->lic_next;
-       ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
+       ASSERT(!xfs_lic_are_all_free(licp));
        for (i = 0; i < licp->lic_unused; i++) {
-               if (XFS_LIC_ISFREE(licp, i)) {
+               if (xfs_lic_isfree(licp, i)) {
                        continue;
                }
 
-               return XFS_LIC_SLOT(licp, i);
+               return xfs_lic_slot(licp, i);
        }
        ASSERT(0);
        /* NOTREACHED */
@@ -300,9 +300,9 @@ xfs_trans_free_items(
        /*
         * Special case the embedded chunk so we don't free it below.
         */
-       if (!XFS_LIC_ARE_ALL_FREE(licp)) {
+       if (!xfs_lic_are_all_free(licp)) {
                (void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN);
-               XFS_LIC_ALL_FREE(licp);
+               xfs_lic_all_free(licp);
                licp->lic_unused = 0;
        }
        licp = licp->lic_next;
@@ -311,7 +311,7 @@ xfs_trans_free_items(
         * Unlock each item in each chunk and free the chunks.
         */
        while (licp != NULL) {
-               ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
+               ASSERT(!xfs_lic_are_all_free(licp));
                (void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN);
                next_licp = licp->lic_next;
                kmem_free(licp);
@@ -347,7 +347,7 @@ xfs_trans_unlock_items(xfs_trans_t *tp, xfs_lsn_t commit_lsn)
        /*
         * Special case the embedded chunk so we don't free.
         */
-       if (!XFS_LIC_ARE_ALL_FREE(licp)) {
+       if (!xfs_lic_are_all_free(licp)) {
                freed = xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn);
        }
        licpp = &(tp->t_items.lic_next);
@@ -358,10 +358,10 @@ xfs_trans_unlock_items(xfs_trans_t *tp, xfs_lsn_t commit_lsn)
         * and free empty chunks.
         */
        while (licp != NULL) {
-               ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
+               ASSERT(!xfs_lic_are_all_free(licp));
                freed += xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn);
                next_licp = licp->lic_next;
-               if (XFS_LIC_ARE_ALL_FREE(licp)) {
+               if (xfs_lic_are_all_free(licp)) {
                        *licpp = next_licp;
                        kmem_free(licp);
                        freed -= XFS_LIC_NUM_SLOTS;
@@ -402,7 +402,7 @@ xfs_trans_unlock_chunk(
        freed = 0;
        lidp = licp->lic_descs;
        for (i = 0; i < licp->lic_unused; i++, lidp++) {
-               if (XFS_LIC_ISFREE(licp, i)) {
+               if (xfs_lic_isfree(licp, i)) {
                        continue;
                }
                lip = lidp->lid_item;
@@ -421,7 +421,7 @@ xfs_trans_unlock_chunk(
                 */
                if (!(freeing_chunk) &&
                    (!(lidp->lid_flags & XFS_LID_DIRTY) || abort)) {
-                       XFS_LIC_RELSE(licp, i);
+                       xfs_lic_relse(licp, i);
                        freed++;
                }
        }
index 98e5f110ba5f412be32adcc9a2be9205190da9e5..35d4d414bcc273ca0981fad6ed4dddbbf8a9ea42 100644 (file)
@@ -237,7 +237,7 @@ xfs_droplink(
 
        ASSERT (ip->i_d.di_nlink > 0);
        ip->i_d.di_nlink--;
-       drop_nlink(ip->i_vnode);
+       drop_nlink(VFS_I(ip));
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
        error = 0;
@@ -301,7 +301,7 @@ xfs_bumplink(
 
        ASSERT(ip->i_d.di_nlink > 0);
        ip->i_d.di_nlink++;
-       inc_nlink(ip->i_vnode);
+       inc_nlink(VFS_I(ip));
        if ((ip->i_d.di_version == XFS_DINODE_VERSION_1) &&
            (ip->i_d.di_nlink > XFS_MAXLINK_1)) {
                /*
index f316cb85d8e234eb21b573a0a59ddfbccc21a922..ef321225d2698cfa2f5982d24099388d0cdae0eb 100644 (file)
@@ -18,9 +18,6 @@
 #ifndef __XFS_UTILS_H__
 #define __XFS_UTILS_H__
 
-#define IRELE(ip)      VN_RELE(XFS_ITOV(ip))
-#define IHOLD(ip)      VN_HOLD(XFS_ITOV(ip))
-
 extern int xfs_truncate_file(xfs_mount_t *, xfs_inode_t *);
 extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
                                xfs_dev_t, cred_t *, prid_t, int,
index 4a9a43315a8662262906292d0d3c21293644d015..439dd3939dda043d172c5a9b0285085afc042534 100644 (file)
@@ -128,7 +128,6 @@ xfs_unmount_flush(
        xfs_inode_t     *rip = mp->m_rootip;
        xfs_inode_t     *rbmip;
        xfs_inode_t     *rsumip = NULL;
-       bhv_vnode_t     *rvp = XFS_ITOV(rip);
        int             error;
 
        xfs_ilock(rip, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
@@ -146,7 +145,7 @@ xfs_unmount_flush(
                if (error == EFSCORRUPTED)
                        goto fscorrupt_out;
 
-               ASSERT(vn_count(XFS_ITOV(rbmip)) == 1);
+               ASSERT(vn_count(VFS_I(rbmip)) == 1);
 
                rsumip = mp->m_rsumip;
                xfs_ilock(rsumip, XFS_ILOCK_EXCL);
@@ -157,7 +156,7 @@ xfs_unmount_flush(
                if (error == EFSCORRUPTED)
                        goto fscorrupt_out;
 
-               ASSERT(vn_count(XFS_ITOV(rsumip)) == 1);
+               ASSERT(vn_count(VFS_I(rsumip)) == 1);
        }
 
        /*
@@ -167,7 +166,7 @@ xfs_unmount_flush(
        if (error == EFSCORRUPTED)
                goto fscorrupt_out2;
 
-       if (vn_count(rvp) != 1 && !relocation) {
+       if (vn_count(VFS_I(rip)) != 1 && !relocation) {
                xfs_iunlock(rip, XFS_ILOCK_EXCL);
                return XFS_ERROR(EBUSY);
        }
@@ -284,7 +283,7 @@ xfs_sync_inodes(
        int             *bypassed)
 {
        xfs_inode_t     *ip = NULL;
-       bhv_vnode_t     *vp = NULL;
+       struct inode    *vp = NULL;
        int             error;
        int             last_error;
        uint64_t        fflag;
@@ -404,7 +403,7 @@ xfs_sync_inodes(
                        continue;
                }
 
-               vp = XFS_ITOV_NULL(ip);
+               vp = VFS_I(ip);
 
                /*
                 * If the vnode is gone then this is being torn down,
@@ -479,7 +478,7 @@ xfs_sync_inodes(
                        IPOINTER_INSERT(ip, mp);
                        xfs_ilock(ip, lock_flags);
 
-                       ASSERT(vp == XFS_ITOV(ip));
+                       ASSERT(vp == VFS_I(ip));
                        ASSERT(ip->i_mount == mp);
 
                        vnode_refed = B_TRUE;
index 76a1166af8227ac0b45715986bcad98daa469c87..aa238c8fbd7ae605e9f316969bb3012ee4c32f3c 100644 (file)
@@ -83,7 +83,7 @@ xfs_setattr(
        cred_t                  *credp)
 {
        xfs_mount_t             *mp = ip->i_mount;
-       struct inode            *inode = XFS_ITOV(ip);
+       struct inode            *inode = VFS_I(ip);
        int                     mask = iattr->ia_valid;
        xfs_trans_t             *tp;
        int                     code;
@@ -182,7 +182,7 @@ xfs_setattr(
        xfs_ilock(ip, lock_flags);
 
        /* boolean: are we the file owner? */
-       file_owner = (current_fsuid(credp) == ip->i_d.di_uid);
+       file_owner = (current_fsuid() == ip->i_d.di_uid);
 
        /*
         * Change various properties of a file.
@@ -513,7 +513,6 @@ xfs_setattr(
                        ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
                        ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
                        ip->i_update_core = 1;
-                       timeflags &= ~XFS_ICHGTIME_ACC;
                }
                if (mask & ATTR_MTIME) {
                        inode->i_mtime = iattr->ia_mtime;
@@ -714,7 +713,7 @@ xfs_fsync(
                return XFS_ERROR(EIO);
 
        /* capture size updates in I/O completion before writing the inode. */
-       error = filemap_fdatawait(vn_to_inode(XFS_ITOV(ip))->i_mapping);
+       error = filemap_fdatawait(VFS_I(ip)->i_mapping);
        if (error)
                return XFS_ERROR(error);
 
@@ -1160,7 +1159,6 @@ int
 xfs_release(
        xfs_inode_t     *ip)
 {
-       bhv_vnode_t     *vp = XFS_ITOV(ip);
        xfs_mount_t     *mp = ip->i_mount;
        int             error;
 
@@ -1195,13 +1193,13 @@ xfs_release(
                 * be exposed to that problem.
                 */
                truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED);
-               if (truncated && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
+               if (truncated && VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0)
                        xfs_flush_pages(ip, 0, -1, XFS_B_ASYNC, FI_NONE);
        }
 
        if (ip->i_d.di_nlink != 0) {
                if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
-                    ((ip->i_size > 0) || (VN_CACHED(vp) > 0 ||
+                    ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 ||
                       ip->i_delayed_blks > 0)) &&
                     (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
                    (!(ip->i_d.di_flags &
@@ -1227,7 +1225,6 @@ int
 xfs_inactive(
        xfs_inode_t     *ip)
 {
-       bhv_vnode_t     *vp = XFS_ITOV(ip);
        xfs_bmap_free_t free_list;
        xfs_fsblock_t   first_block;
        int             committed;
@@ -1242,7 +1239,7 @@ xfs_inactive(
         * If the inode is already free, then there can be nothing
         * to clean up here.
         */
-       if (ip->i_d.di_mode == 0 || VN_BAD(vp)) {
+       if (ip->i_d.di_mode == 0 || VN_BAD(VFS_I(ip))) {
                ASSERT(ip->i_df.if_real_bytes == 0);
                ASSERT(ip->i_df.if_broot_bytes == 0);
                return VN_INACTIVE_CACHE;
@@ -1272,7 +1269,7 @@ xfs_inactive(
 
        if (ip->i_d.di_nlink != 0) {
                if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
-                     ((ip->i_size > 0) || (VN_CACHED(vp) > 0 ||
+                     ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 ||
                        ip->i_delayed_blks > 0)) &&
                      (ip->i_df.if_flags & XFS_IFEXTENTS) &&
                     (!(ip->i_d.di_flags &
@@ -1536,7 +1533,7 @@ xfs_create(
         * Make sure that we have allocated dquot(s) on disk.
         */
        error = XFS_QM_DQVOPALLOC(mp, dp,
-                       current_fsuid(credp), current_fsgid(credp), prid,
+                       current_fsuid(), current_fsgid(), prid,
                        XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp);
        if (error)
                goto std_return;
@@ -1707,111 +1704,6 @@ std_return:
        goto std_return;
 }
 
-#ifdef DEBUG
-/*
- * Some counters to see if (and how often) we are hitting some deadlock
- * prevention code paths.
- */
-
-int xfs_rm_locks;
-int xfs_rm_lock_delays;
-int xfs_rm_attempts;
-#endif
-
-/*
- * The following routine will lock the inodes associated with the
- * directory and the named entry in the directory. The locks are
- * acquired in increasing inode number.
- *
- * If the entry is "..", then only the directory is locked. The
- * vnode ref count will still include that from the .. entry in
- * this case.
- *
- * There is a deadlock we need to worry about. If the locked directory is
- * in the AIL, it might be blocking up the log. The next inode we lock
- * could be already locked by another thread waiting for log space (e.g
- * a permanent log reservation with a long running transaction (see
- * xfs_itruncate_finish)). To solve this, we must check if the directory
- * is in the ail and use lock_nowait. If we can't lock, we need to
- * drop the inode lock on the directory and try again. xfs_iunlock will
- * potentially push the tail if we were holding up the log.
- */
-STATIC int
-xfs_lock_dir_and_entry(
-       xfs_inode_t     *dp,
-       xfs_inode_t     *ip)    /* inode of entry 'name' */
-{
-       int             attempts;
-       xfs_ino_t       e_inum;
-       xfs_inode_t     *ips[2];
-       xfs_log_item_t  *lp;
-
-#ifdef DEBUG
-       xfs_rm_locks++;
-#endif
-       attempts = 0;
-
-again:
-       xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
-
-       e_inum = ip->i_ino;
-
-       xfs_itrace_ref(ip);
-
-       /*
-        * We want to lock in increasing inum. Since we've already
-        * acquired the lock on the directory, we may need to release
-        * if if the inum of the entry turns out to be less.
-        */
-       if (e_inum > dp->i_ino) {
-               /*
-                * We are already in the right order, so just
-                * lock on the inode of the entry.
-                * We need to use nowait if dp is in the AIL.
-                */
-
-               lp = (xfs_log_item_t *)dp->i_itemp;
-               if (lp && (lp->li_flags & XFS_LI_IN_AIL)) {
-                       if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
-                               attempts++;
-#ifdef DEBUG
-                               xfs_rm_attempts++;
-#endif
-
-                               /*
-                                * Unlock dp and try again.
-                                * xfs_iunlock will try to push the tail
-                                * if the inode is in the AIL.
-                                */
-
-                               xfs_iunlock(dp, XFS_ILOCK_EXCL);
-
-                               if ((attempts % 5) == 0) {
-                                       delay(1); /* Don't just spin the CPU */
-#ifdef DEBUG
-                                       xfs_rm_lock_delays++;
-#endif
-                               }
-                               goto again;
-                       }
-               } else {
-                       xfs_ilock(ip, XFS_ILOCK_EXCL);
-               }
-       } else if (e_inum < dp->i_ino) {
-               xfs_iunlock(dp, XFS_ILOCK_EXCL);
-
-               ips[0] = ip;
-               ips[1] = dp;
-               xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL);
-       }
-       /* else  e_inum == dp->i_ino */
-       /*     This can happen if we're asked to lock /x/..
-        *     the entry is "..", which is also the parent directory.
-        */
-
-       return 0;
-}
-
 #ifdef DEBUG
 int xfs_locked_n;
 int xfs_small_retries;
@@ -1946,6 +1838,45 @@ again:
 #endif
 }
 
+void
+xfs_lock_two_inodes(
+       xfs_inode_t             *ip0,
+       xfs_inode_t             *ip1,
+       uint                    lock_mode)
+{
+       xfs_inode_t             *temp;
+       int                     attempts = 0;
+       xfs_log_item_t          *lp;
+
+       ASSERT(ip0->i_ino != ip1->i_ino);
+
+       if (ip0->i_ino > ip1->i_ino) {
+               temp = ip0;
+               ip0 = ip1;
+               ip1 = temp;
+       }
+
+ again:
+       xfs_ilock(ip0, xfs_lock_inumorder(lock_mode, 0));
+
+       /*
+        * If the first lock we have locked is in the AIL, we must TRY to get
+        * the second lock. If we can't get it, we must release the first one
+        * and try again.
+        */
+       lp = (xfs_log_item_t *)ip0->i_itemp;
+       if (lp && (lp->li_flags & XFS_LI_IN_AIL)) {
+               if (!xfs_ilock_nowait(ip1, xfs_lock_inumorder(lock_mode, 1))) {
+                       xfs_iunlock(ip0, lock_mode);
+                       if ((++attempts % 5) == 0)
+                               delay(1); /* Don't just spin the CPU */
+                       goto again;
+               }
+       } else {
+               xfs_ilock(ip1, xfs_lock_inumorder(lock_mode, 1));
+       }
+}
+
 int
 xfs_remove(
        xfs_inode_t             *dp,
@@ -2018,9 +1949,7 @@ xfs_remove(
                goto out_trans_cancel;
        }
 
-       error = xfs_lock_dir_and_entry(dp, ip);
-       if (error)
-               goto out_trans_cancel;
+       xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL);
 
        /*
         * At this point, we've gotten both the directory and the entry
@@ -2047,9 +1976,6 @@ xfs_remove(
                }
        }
 
-       /*
-        * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
-        */
        XFS_BMAP_INIT(&free_list, &first_block);
        error = xfs_dir_removename(tp, dp, name, ip->i_ino,
                                        &first_block, &free_list, resblks);
@@ -2155,7 +2081,6 @@ xfs_link(
 {
        xfs_mount_t             *mp = tdp->i_mount;
        xfs_trans_t             *tp;
-       xfs_inode_t             *ips[2];
        int                     error;
        xfs_bmap_free_t         free_list;
        xfs_fsblock_t           first_block;
@@ -2203,15 +2128,7 @@ xfs_link(
                goto error_return;
        }
 
-       if (sip->i_ino < tdp->i_ino) {
-               ips[0] = sip;
-               ips[1] = tdp;
-       } else {
-               ips[0] = tdp;
-               ips[1] = sip;
-       }
-
-       xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL);
+       xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL);
 
        /*
         * Increment vnode ref counts since xfs_trans_commit &
@@ -2352,7 +2269,7 @@ xfs_mkdir(
         * Make sure that we have allocated dquot(s) on disk.
         */
        error = XFS_QM_DQVOPALLOC(mp, dp,
-                       current_fsuid(credp), current_fsgid(credp), prid,
+                       current_fsuid(), current_fsgid(), prid,
                        XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
        if (error)
                goto std_return;
@@ -2578,7 +2495,7 @@ xfs_symlink(
         * Make sure that we have allocated dquot(s) on disk.
         */
        error = XFS_QM_DQVOPALLOC(mp, dp,
-                       current_fsuid(credp), current_fsgid(credp), prid,
+                       current_fsuid(), current_fsgid(), prid,
                        XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
        if (error)
                goto std_return;
@@ -2873,14 +2790,13 @@ int
 xfs_reclaim(
        xfs_inode_t     *ip)
 {
-       bhv_vnode_t     *vp = XFS_ITOV(ip);
 
        xfs_itrace_entry(ip);
 
-       ASSERT(!VN_MAPPED(vp));
+       ASSERT(!VN_MAPPED(VFS_I(ip)));
 
        /* bad inode, get out here ASAP */
-       if (VN_BAD(vp)) {
+       if (VN_BAD(VFS_I(ip))) {
                xfs_ireclaim(ip);
                return 0;
        }
@@ -2917,7 +2833,7 @@ xfs_reclaim(
                XFS_MOUNT_ILOCK(mp);
                spin_lock(&ip->i_flags_lock);
                __xfs_iflags_set(ip, XFS_IRECLAIMABLE);
-               vn_to_inode(vp)->i_private = NULL;
+               VFS_I(ip)->i_private = NULL;
                ip->i_vnode = NULL;
                spin_unlock(&ip->i_flags_lock);
                list_add_tail(&ip->i_reclaim, &mp->m_del_inodes);
@@ -2933,7 +2849,7 @@ xfs_finish_reclaim(
        int             sync_mode)
 {
        xfs_perag_t     *pag = xfs_get_perag(ip->i_mount, ip->i_ino);
-       bhv_vnode_t     *vp = XFS_ITOV_NULL(ip);
+       struct inode    *vp = VFS_I(ip);
 
        if (vp && VN_BAD(vp))
                goto reclaim;
@@ -3321,7 +3237,6 @@ xfs_free_file_space(
        xfs_off_t               len,
        int                     attr_flags)
 {
-       bhv_vnode_t             *vp;
        int                     committed;
        int                     done;
        xfs_off_t               end_dmi_offset;
@@ -3341,7 +3256,6 @@ xfs_free_file_space(
        xfs_trans_t             *tp;
        int                     need_iolock = 1;
 
-       vp = XFS_ITOV(ip);
        mp = ip->i_mount;
 
        xfs_itrace_entry(ip);
@@ -3378,7 +3292,7 @@ xfs_free_file_space(
        rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
        ioffset = offset & ~(rounding - 1);
 
-       if (VN_CACHED(vp) != 0) {
+       if (VN_CACHED(VFS_I(ip)) != 0) {
                xfs_inval_cached_trace(ip, ioffset, -1, ioffset, -1);
                error = xfs_flushinval_pages(ip, ioffset, -1, FI_REMAPF_LOCKED);
                if (error)
index 714207a1c38795fa40168373ee3858e74bffa607..f5705761a37b14509c5603e79c69292fdb4adb66 100644 (file)
@@ -9,8 +9,8 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 
-#ifndef _ASM_A_OUT_CORE_H
-#define _ASM_A_OUT_CORE_H
+#ifndef ASM_X86__A_OUT_CORE_H
+#define ASM_X86__A_OUT_CORE_H
 
 #ifdef __KERNEL__
 #ifdef CONFIG_X86_32
@@ -70,4 +70,4 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
 
 #endif /* CONFIG_X86_32 */
 #endif /* __KERNEL__ */
-#endif /* _ASM_A_OUT_CORE_H */
+#endif /* ASM_X86__A_OUT_CORE_H */
index 4684f97a5bbd1b1edce881a88e75393b580a2cd1..0948748bc69c1dd8f694c34878551868e01a3da7 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_A_OUT_H
-#define _ASM_X86_A_OUT_H
+#ifndef ASM_X86__A_OUT_H
+#define ASM_X86__A_OUT_H
 
 struct exec
 {
@@ -17,4 +17,4 @@ struct exec
 #define N_DRSIZE(a)    ((a).a_drsize)
 #define N_SYMSIZE(a)   ((a).a_syms)
 
-#endif /* _ASM_X86_A_OUT_H */
+#endif /* ASM_X86__A_OUT_H */
index 635d764dc13e346e26dc6f27b8a45d5701a9c55b..bd76299586b33610b154777a0bc988e526d65541 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_ACPI_H
-#define _ASM_X86_ACPI_H
+#ifndef ASM_X86__ACPI_H
+#define ASM_X86__ACPI_H
 
 /*
  *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -173,4 +173,4 @@ static inline void acpi_fake_nodes(const struct bootnode *fake_nodes,
 
 #define acpi_unlazy_tlb(x)     leave_mm(x)
 
-#endif /*__X86_ASM_ACPI_H*/
+#endif /* ASM_X86__ACPI_H */
index e4004a9f6a9a53fa03c7b5ce6db80809180dc703..3617fd4fcdf9faa1f110055cd33f607e98662c76 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_AGP_H
-#define _ASM_X86_AGP_H
+#ifndef ASM_X86__AGP_H
+#define ASM_X86__AGP_H
 
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
@@ -32,4 +32,4 @@
 #define free_gatt_pages(table, order)  \
        free_pages((unsigned long)(table), (order))
 
-#endif
+#endif /* ASM_X86__AGP_H */
index f6aa18eadf71717d9e86c53ac3719776fa035969..22d3c9862bf3b3a0967df0c9c2f2b7038d6e1ba3 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_ALTERNATIVE_H
-#define _ASM_X86_ALTERNATIVE_H
+#ifndef ASM_X86__ALTERNATIVE_H
+#define ASM_X86__ALTERNATIVE_H
 
 #include <linux/types.h>
 #include <linux/stddef.h>
@@ -180,4 +180,4 @@ extern void add_nops(void *insns, unsigned int len);
 extern void *text_poke(void *addr, const void *opcode, size_t len);
 extern void *text_poke_early(void *addr, const void *opcode, size_t len);
 
-#endif /* _ASM_X86_ALTERNATIVE_H */
+#endif /* ASM_X86__ALTERNATIVE_H */
index 30a12049353b1bc6c17d9811046f71096b9d6759..783f43e580523e0af5193807b9e670cace005c7d 100644 (file)
@@ -17,8 +17,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#ifndef _ASM_X86_AMD_IOMMU_H
-#define _ASM_X86_AMD_IOMMU_H
+#ifndef ASM_X86__AMD_IOMMU_H
+#define ASM_X86__AMD_IOMMU_H
 
 #ifdef CONFIG_AMD_IOMMU
 extern int amd_iommu_init(void);
@@ -29,4 +29,4 @@ static inline int amd_iommu_init(void) { return -ENODEV; }
 static inline void amd_iommu_detect(void) { }
 #endif
 
-#endif
+#endif /* ASM_X86__AMD_IOMMU_H */
index 22aa58ca1991c3003565f8fbc0313f3cf37b9d92..e6b4d5b083701e730b22fbe9e91142ad77ee4895 100644 (file)
@@ -17,8 +17,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#ifndef __AMD_IOMMU_TYPES_H__
-#define __AMD_IOMMU_TYPES_H__
+#ifndef ASM_X86__AMD_IOMMU_TYPES_H
+#define ASM_X86__AMD_IOMMU_TYPES_H
 
 #include <linux/types.h>
 #include <linux/list.h>
@@ -339,4 +339,4 @@ static inline u16 calc_devid(u8 bus, u8 devfn)
        return (((u16)bus) << 8) | devfn;
 }
 
-#endif
+#endif /* ASM_X86__AMD_IOMMU_TYPES_H */
index 519ad65708e7e6ea408f94ddd8c35c733ed015d4..1311c82b165bf45ad373c6af43a2193de00a013a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_APIC_H
-#define _ASM_X86_APIC_H
+#ifndef ASM_X86__APIC_H
+#define ASM_X86__APIC_H
 
 #include <linux/pm.h>
 #include <linux/delay.h>
@@ -9,6 +9,8 @@
 #include <asm/apicdef.h>
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/cpufeature.h>
+#include <asm/msr.h>
 
 #define ARCH_APICTIMER_STOPS_ON_C3     1
 
@@ -47,8 +49,6 @@ extern int disable_apic;
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else
-#define apic_write native_apic_write
-#define apic_read native_apic_read
 #define setup_boot_clock setup_boot_APIC_clock
 #define setup_secondary_clock setup_secondary_APIC_clock
 #endif
@@ -60,7 +60,7 @@ extern u64 xapic_icr_read(void);
 extern void xapic_icr_write(u32, u32);
 extern int setup_profiling_timer(unsigned int);
 
-static inline void native_apic_write(unsigned long reg, u32 v)
+static inline void native_apic_mem_write(u32 reg, u32 v)
 {
        volatile u32 *addr = (volatile u32 *)(APIC_BASE + reg);
 
@@ -69,15 +69,68 @@ static inline void native_apic_write(unsigned long reg, u32 v)
                       ASM_OUTPUT2("0" (v), "m" (*addr)));
 }
 
-static inline u32 native_apic_read(unsigned long reg)
+static inline u32 native_apic_mem_read(u32 reg)
 {
        return *((volatile u32 *)(APIC_BASE + reg));
 }
 
-extern void apic_wait_icr_idle(void);
-extern u32 safe_apic_wait_icr_idle(void);
+static inline void native_apic_msr_write(u32 reg, u32 v)
+{
+       if (reg == APIC_DFR || reg == APIC_ID || reg == APIC_LDR ||
+           reg == APIC_LVR)
+               return;
+
+       wrmsr(APIC_BASE_MSR + (reg >> 4), v, 0);
+}
+
+static inline u32 native_apic_msr_read(u32 reg)
+{
+       u32 low, high;
+
+       if (reg == APIC_DFR)
+               return -1;
+
+       rdmsr(APIC_BASE_MSR + (reg >> 4), low, high);
+       return low;
+}
+
+#ifndef CONFIG_X86_32
+extern int x2apic, x2apic_preenabled;
+extern void check_x2apic(void);
+extern void enable_x2apic(void);
+extern void enable_IR_x2apic(void);
+extern void x2apic_icr_write(u32 low, u32 id);
+#endif
+
+struct apic_ops {
+       u32 (*read)(u32 reg);
+       void (*write)(u32 reg, u32 v);
+       u64 (*icr_read)(void);
+       void (*icr_write)(u32 low, u32 high);
+       void (*wait_icr_idle)(void);
+       u32 (*safe_wait_icr_idle)(void);
+};
+
+extern struct apic_ops *apic_ops;
+
+#define apic_read (apic_ops->read)
+#define apic_write (apic_ops->write)
+#define apic_icr_read (apic_ops->icr_read)
+#define apic_icr_write (apic_ops->icr_write)
+#define apic_wait_icr_idle (apic_ops->wait_icr_idle)
+#define safe_apic_wait_icr_idle (apic_ops->safe_wait_icr_idle)
+
 extern int get_physical_broadcast(void);
 
+#ifdef CONFIG_X86_64
+static inline void ack_x2APIC_irq(void)
+{
+       /* Docs say use 0 for future compatibility */
+       native_apic_msr_write(APIC_EOI, 0);
+}
+#endif
+
+
 static inline void ack_APIC_irq(void)
 {
        /*
@@ -133,4 +186,4 @@ static inline void init_apic_mappings(void) { }
 
 #endif /* !CONFIG_X86_LOCAL_APIC */
 
-#endif /* __ASM_APIC_H */
+#endif /* ASM_X86__APIC_H */
index 6b9008c787319d1040c9520c137a454f24afc06a..b922c85ac91d8ab0e3f8fbd6c993f22ffe047879 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_APICDEF_H
-#define _ASM_X86_APICDEF_H
+#ifndef ASM_X86__APICDEF_H
+#define ASM_X86__APICDEF_H
 
 /*
  * Constants for various Intel APICs. (local APIC, IOAPIC, etc.)
 #define        APIC_TMICT      0x380
 #define        APIC_TMCCT      0x390
 #define        APIC_TDCR       0x3E0
+#define APIC_SELF_IPI  0x3F0
 #define                APIC_TDR_DIV_TMBASE     (1 << 2)
 #define                APIC_TDR_DIV_1          0xB
 #define                APIC_TDR_DIV_2          0x0
 #define        APIC_EILVT3     0x530
 
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
+#define APIC_BASE_MSR  0x800
+#define X2APIC_ENABLE  (1UL << 10)
 
 #ifdef CONFIG_X86_32
 # define MAX_IO_APICS 64
@@ -411,4 +414,4 @@ struct local_apic {
 #else
  #define BAD_APICID 0xFFFFu
 #endif
-#endif
+#endif /* ASM_X86__APICDEF_H */
index 8411750ceb633763ad2fda66d8f154f9b87cfd7f..de4596b24c23a8e4a0e14135125d051f25a3fcdf 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_ARCH_HOOKS_H
-#define _ASM_ARCH_HOOKS_H
+#ifndef ASM_X86__ARCH_HOOKS_H
+#define ASM_X86__ARCH_HOOKS_H
 
 #include <linux/interrupt.h>
 
@@ -12,8 +12,6 @@
 /* these aren't arch hooks, they are generic routines
  * that can be used by the hooks */
 extern void init_ISA_irqs(void);
-extern void apic_intr_init(void);
-extern void smp_intr_init(void);
 extern irqreturn_t timer_interrupt(int irq, void *dev_id);
 
 /* these are the defined hooks */
@@ -25,4 +23,4 @@ extern void pre_time_init_hook(void);
 extern void time_init_hook(void);
 extern void mca_nmi_hook(void);
 
-#endif
+#endif /* ASM_X86__ARCH_HOOKS_H */
index 97220321f39de383b4624533a7ae1969756fb0b6..2439ae49e8ac9bbc0cb54eb1ad13de79861f7cb5 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_ASM_H
-#define _ASM_X86_ASM_H
+#ifndef ASM_X86__ASM_H
+#define ASM_X86__ASM_H
 
 #ifdef __ASSEMBLY__
 # define __ASM_FORM(x) x
@@ -39,4 +39,4 @@
        _ASM_PTR #from "," #to "\n" \
        " .previous\n"
 
-#endif /* _ASM_X86_ASM_H */
+#endif /* ASM_X86__ASM_H */
index 21a4825148c09e34c70db728f68951ff32e631f8..14d3f0beb889917c3d6af356bdd84d114a7cae06 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ARCH_I386_ATOMIC__
-#define __ARCH_I386_ATOMIC__
+#ifndef ASM_X86__ATOMIC_32_H
+#define ASM_X86__ATOMIC_32_H
 
 #include <linux/compiler.h>
 #include <asm/processor.h>
@@ -256,4 +256,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 #define smp_mb__after_atomic_inc()     barrier()
 
 #include <asm-generic/atomic.h>
-#endif
+#endif /* ASM_X86__ATOMIC_32_H */
index a0095191c02e92f319c13b2d3bc27fcd2f1fbc70..ebbc753af6ab5712177ed53b75875505ef06e1b1 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ARCH_X86_64_ATOMIC__
-#define __ARCH_X86_64_ATOMIC__
+#ifndef ASM_X86__ATOMIC_64_H
+#define ASM_X86__ATOMIC_64_H
 
 #include <asm/alternative.h>
 #include <asm/cmpxchg.h>
@@ -470,4 +470,4 @@ static inline void atomic_or_long(unsigned long *v1, unsigned long v2)
 #define smp_mb__after_atomic_inc()     barrier()
 
 #include <asm-generic/atomic.h>
-#endif
+#endif /* ASM_X86__ATOMIC_64_H */
index 87f5e6d5a02075244fbd3ad2087ae9a8c9e4405a..12c7cac7420202c7a4a11997187b966bc4d392c4 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_AUXVEC_H
-#define _ASM_X86_AUXVEC_H
+#ifndef ASM_X86__AUXVEC_H
+#define ASM_X86__AUXVEC_H
 /*
  * Architecture-neutral AT_ values in 0-17, leave some room
  * for more of them, start the x86-specific ones at 32.
@@ -9,4 +9,4 @@
 #endif
 #define AT_SYSINFO_EHDR                33
 
-#endif
+#endif /* ASM_X86__AUXVEC_H */
similarity index 98%
rename from include/asm-x86/mach-bigsmp/mach_apic.h
rename to include/asm-x86/bigsmp/apic.h
index c3b9dc6970c95726a3adaafe5502334b9d64c68c..0a9cd7c5ca0c8813ddb6899f1ad2a776cb9a85e1 100644 (file)
@@ -11,7 +11,7 @@ static inline int apic_id_registered(void)
 
 /* Round robin the irqs amoung the online cpus */
 static inline cpumask_t target_cpus(void)
-{ 
+{
        static unsigned long cpu = NR_CPUS;
        do {
                if (cpu >= NR_CPUS)
@@ -23,7 +23,7 @@ static inline cpumask_t target_cpus(void)
 }
 
 #undef APIC_DEST_LOGICAL
-#define APIC_DEST_LOGICAL      0
+#define APIC_DEST_LOGICAL      0
 #define TARGET_CPUS            (target_cpus())
 #define APIC_DFR_VALUE         (APIC_DFR_FLAT)
 #define INT_DELIVERY_MODE      (dest_Fixed)
similarity index 74%
rename from include/asm-x86/mach-bigsmp/mach_apicdef.h
rename to include/asm-x86/bigsmp/apicdef.h
index a58ab5a75c8c57c5743a15f4f0fc1587f182a492..392c3f5ef2fe0ad4d3e48e485390f4cb62a7bf83 100644 (file)
@@ -3,10 +3,10 @@
 
 #define                APIC_ID_MASK            (0xFF<<24)
 
-static inline unsigned get_apic_id(unsigned long x) 
-{ 
+static inline unsigned get_apic_id(unsigned long x)
+{
        return (((x)>>24)&0xFF);
-} 
+}
 
 #define                GET_APIC_ID(x)  get_apic_id(x)
 
index 0033e50c13b28cec6bfcd479ced48e01798e9e76..ec42ed8745913383cbb81be7c28556c4ddbacdd0 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _MACH_BIOS_EBDA_H
-#define _MACH_BIOS_EBDA_H
+#ifndef ASM_X86__BIOS_EBDA_H
+#define ASM_X86__BIOS_EBDA_H
 
 #include <asm/io.h>
 
@@ -16,4 +16,4 @@ static inline unsigned int get_bios_ebda(void)
 
 void reserve_ebda_region(void);
 
-#endif /* _MACH_BIOS_EBDA_H */
+#endif /* ASM_X86__BIOS_EBDA_H */
index cfb2b64f76e7d645a8418426f71239b80250c5bb..61989b93b4753db3f5758ba82308431379b1edda 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_BITOPS_H
-#define _ASM_X86_BITOPS_H
+#ifndef ASM_X86__BITOPS_H
+#define ASM_X86__BITOPS_H
 
 /*
  * Copyright 1992, Linus Torvalds.
@@ -458,4 +458,4 @@ static inline void set_bit_string(unsigned long *bitmap,
 #include <asm-generic/bitops/minix.h>
 
 #endif /* __KERNEL__ */
-#endif /* _ASM_X86_BITOPS_H */
+#endif /* ASM_X86__BITOPS_H */
index 2faed7ecb092a7893c89c573b7ac9870e060d8a7..825de5dc867cb97240a90ba3abc1c2933f3fee07 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_BOOT_H
-#define _ASM_BOOT_H
+#ifndef ASM_X86__BOOT_H
+#define ASM_X86__BOOT_H
 
 /* Don't touch these, unless you really know what you're doing. */
 #define DEF_INITSEG    0x9000
@@ -25,4 +25,4 @@
 #define BOOT_STACK_SIZE        0x1000
 #endif
 
-#endif /* _ASM_BOOT_H */
+#endif /* ASM_X86__BOOT_H */
index ae22bdf0ab14a74c4b9d01f91fb07230047e1cee..ccf027e2d97da02eabaab3d54eea8bd4fe727d87 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_BOOTPARAM_H
-#define _ASM_BOOTPARAM_H
+#ifndef ASM_X86__BOOTPARAM_H
+#define ASM_X86__BOOTPARAM_H
 
 #include <linux/types.h>
 #include <linux/screen_info.h>
@@ -108,4 +108,4 @@ struct boot_params {
        __u8  _pad9[276];                               /* 0xeec */
 } __attribute__((packed));
 
-#endif /* _ASM_BOOTPARAM_H */
+#endif /* ASM_X86__BOOTPARAM_H */
index b69aa64b82a4af9e60573253abdb5a9c07ebc8e8..91ad43a54c47c6f9b9cb28bfc3cb7003a7b666a1 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_BUG_H
-#define _ASM_X86_BUG_H
+#ifndef ASM_X86__BUG_H
+#define ASM_X86__BUG_H
 
 #ifdef CONFIG_BUG
 #define HAVE_ARCH_BUG
@@ -36,4 +36,4 @@ do {                                                          \
 #endif /* !CONFIG_BUG */
 
 #include <asm-generic/bug.h>
-#endif
+#endif /* ASM_X86__BUG_H */
index 021cbdd5f258a7739c2433d62f00a37a51070a4b..4761c461d23a62a4ba44e015c106bd5d5bdbd02c 100644 (file)
@@ -1,7 +1,7 @@
-#ifndef _ASM_X86_BUGS_H
-#define _ASM_X86_BUGS_H
+#ifndef ASM_X86__BUGS_H
+#define ASM_X86__BUGS_H
 
 extern void check_bugs(void);
 int ppro_with_ram_bug(void);
 
-#endif /* _ASM_X86_BUGS_H */
+#endif /* ASM_X86__BUGS_H */
index e02ae2d89acf13936aad26502e485aa6ddae0b65..722f27d68105f8e454ccaf01d1b7de4baa8dd0ce 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_BYTEORDER_H
-#define _ASM_X86_BYTEORDER_H
+#ifndef ASM_X86__BYTEORDER_H
+#define ASM_X86__BYTEORDER_H
 
 #include <asm/types.h>
 #include <linux/compiler.h>
@@ -78,4 +78,4 @@ static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
 
 #include <linux/byteorder/little_endian.h>
 
-#endif /* _ASM_X86_BYTEORDER_H */
+#endif /* ASM_X86__BYTEORDER_H */
index 1e0bac86f38f8ee4f950380e4e1845a49fec6b30..ea3f1cc06a974e8d3255bb07e74777f390976afa 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ARCH_X86_CACHE_H
-#define _ARCH_X86_CACHE_H
+#ifndef ASM_X86__CACHE_H
+#define ASM_X86__CACHE_H
 
 /* L1 cache line size */
 #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT)
@@ -17,4 +17,4 @@
 #endif
 #endif
 
-#endif
+#endif /* ASM_X86__CACHE_H */
index f4c0ab50d2c2bc4d8e5d5beea1c84c26409225d7..59859cb28a36ce486478f147f79c7bdfa26ae5f7 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_CACHEFLUSH_H
-#define _ASM_X86_CACHEFLUSH_H
+#ifndef ASM_X86__CACHEFLUSH_H
+#define ASM_X86__CACHEFLUSH_H
 
 /* Keep includes the same across arches.  */
 #include <linux/mm.h>
@@ -112,4 +112,4 @@ static inline int rodata_test(void)
 }
 #endif
 
-#endif
+#endif /* ASM_X86__CACHEFLUSH_H */
index 67f60406e2d8136ac50b3b25afefef629508ec0d..933fd272f82663c6ed0c2224df4e668a0870681c 100644 (file)
@@ -21,8 +21,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#ifndef _ASM_X86_64_CALGARY_H
-#define _ASM_X86_64_CALGARY_H
+#ifndef ASM_X86__CALGARY_H
+#define ASM_X86__CALGARY_H
 
 #include <linux/spinlock.h>
 #include <linux/device.h>
@@ -69,4 +69,4 @@ static inline int calgary_iommu_init(void) { return 1; }
 static inline void detect_calgary(void) { return; }
 #endif
 
-#endif /* _ASM_X86_64_CALGARY_H */
+#endif /* ASM_X86__CALGARY_H */
index 52bbb0d8c4c15ce08c2d155fc23f031b98384547..d041e8cda227a6b191f70052599b00383af83ea7 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _I386_CHECKSUM_H
-#define _I386_CHECKSUM_H
+#ifndef ASM_X86__CHECKSUM_32_H
+#define ASM_X86__CHECKSUM_32_H
 
 #include <linux/in6.h>
 
@@ -186,4 +186,4 @@ static inline __wsum csum_and_copy_to_user(const void *src,
        return (__force __wsum)-1; /* invalid checksum */
 }
 
-#endif
+#endif /* ASM_X86__CHECKSUM_32_H */
index 8bd861cc5267094b38fb43f2452b4578d87fb405..110f403beb8953d60218bc5b8c940b9f92dc80bd 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _X86_64_CHECKSUM_H
-#define _X86_64_CHECKSUM_H
+#ifndef ASM_X86__CHECKSUM_64_H
+#define ASM_X86__CHECKSUM_64_H
 
 /*
  * Checksums for x86-64
@@ -188,4 +188,4 @@ static inline unsigned add32_with_carry(unsigned a, unsigned b)
        return a;
 }
 
-#endif
+#endif /* ASM_X86__CHECKSUM_64_H */
index bf5a69d1329ef827a636778829a42bae261910aa..0622e45cdf7cf2b26413e506ef98a0352d6fb400 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_CMPXCHG_H
-#define __ASM_CMPXCHG_H
+#ifndef ASM_X86__CMPXCHG_32_H
+#define ASM_X86__CMPXCHG_32_H
 
 #include <linux/bitops.h> /* for LOCK_PREFIX */
 
@@ -341,4 +341,4 @@ extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
 
 #endif
 
-#endif
+#endif /* ASM_X86__CMPXCHG_32_H */
index 17463ccf816618b59a144ec76f57e51589e8866c..63c1a5e61b994a781ef3ff8e9c1f858e9afac264 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_CMPXCHG_H
-#define __ASM_CMPXCHG_H
+#ifndef ASM_X86__CMPXCHG_64_H
+#define ASM_X86__CMPXCHG_64_H
 
 #include <asm/alternative.h> /* Provides LOCK_PREFIX */
 
@@ -182,4 +182,4 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
        cmpxchg_local((ptr), (o), (n));                                 \
 })
 
-#endif
+#endif /* ASM_X86__CMPXCHG_64_H */
index 1793ac317a30417523cc84fb5d4b2f583b1b4a01..6732b150949e8c8ef0b333673c5b92438c3a9a9e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_64_COMPAT_H
-#define _ASM_X86_64_COMPAT_H
+#ifndef ASM_X86__COMPAT_H
+#define ASM_X86__COMPAT_H
 
 /*
  * Architecture specific compatibility types
@@ -215,4 +215,4 @@ static inline int is_compat_task(void)
        return current_thread_info()->status & TS_COMPAT;
 }
 
-#endif /* _ASM_X86_64_COMPAT_H */
+#endif /* ASM_X86__COMPAT_H */
index 73f2ea84fd74b024fa4ebc8e91cabcdab4340108..83a115083f0d74ad3eb0f82eae64e19aea5a7cc1 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_I386_CPU_H_
-#define _ASM_I386_CPU_H_
+#ifndef ASM_X86__CPU_H
+#define ASM_X86__CPU_H
 
 #include <linux/device.h>
 #include <linux/cpu.h>
@@ -17,4 +17,4 @@ extern void arch_unregister_cpu(int);
 #endif
 
 DECLARE_PER_CPU(int, cpu_state);
-#endif /* _ASM_I386_CPU_H_ */
+#endif /* ASM_X86__CPU_H */
index 2f5a792b0accafba2c93abc31e28157124a4a322..42afe9ca3a37e40cb0d2b172245b042e6fcde05f 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Defines x86 CPU feature bits
  */
-#ifndef _ASM_X86_CPUFEATURE_H
-#define _ASM_X86_CPUFEATURE_H
+#ifndef ASM_X86__CPUFEATURE_H
+#define ASM_X86__CPUFEATURE_H
 
 #include <asm/required-features.h>
 
@@ -91,6 +91,7 @@
 #define X86_FEATURE_CX16       (4*32+13) /* CMPXCHG16B */
 #define X86_FEATURE_XTPR       (4*32+14) /* Send Task Priority Messages */
 #define X86_FEATURE_DCA                (4*32+18) /* Direct Cache Access */
+#define X86_FEATURE_X2APIC     (4*32+21) /* x2APIC */
 
 /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
 #define X86_FEATURE_XSTORE     (5*32+ 2) /* on-CPU RNG present (xstore insn) */
@@ -189,6 +190,7 @@ extern const char * const x86_power_flags[32];
 #define cpu_has_gbpages                boot_cpu_has(X86_FEATURE_GBPAGES)
 #define cpu_has_arch_perfmon   boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
 #define cpu_has_pat            boot_cpu_has(X86_FEATURE_PAT)
+#define cpu_has_x2apic         boot_cpu_has(X86_FEATURE_X2APIC)
 
 #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
 # define cpu_has_invlpg                1
@@ -220,4 +222,4 @@ extern const char * const x86_power_flags[32];
 
 #endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
 
-#endif /* _ASM_X86_CPUFEATURE_H */
+#endif /* ASM_X86__CPUFEATURE_H */
index 7515c19d498884d770e901740eb506d5f96c4807..a863ead856f3d37de49d023a156f98b1d4f540c5 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _X86_CURRENT_H
-#define _X86_CURRENT_H
+#ifndef ASM_X86__CURRENT_H
+#define ASM_X86__CURRENT_H
 
 #ifdef CONFIG_X86_32
 #include <linux/compiler.h>
@@ -36,4 +36,4 @@ static __always_inline struct task_struct *get_current(void)
 
 #define current get_current()
 
-#endif /* X86_CURRENT_H */
+#endif /* ASM_X86__CURRENT_H */
index c6344d572b033a78d04d1219f9772f6fab8b7f06..ecb6907c3ea4ff97ef7aacb4b9c47809ef2701c4 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_DEBUGREG_H
-#define _ASM_X86_DEBUGREG_H
+#ifndef ASM_X86__DEBUGREG_H
+#define ASM_X86__DEBUGREG_H
 
 
 /* Indicate the register numbers for a number of the specific
@@ -67,4 +67,4 @@
 #define DR_LOCAL_SLOWDOWN (0x100)   /* Local slow the pipeline */
 #define DR_GLOBAL_SLOWDOWN (0x200)  /* Global slow the pipeline */
 
-#endif
+#endif /* ASM_X86__DEBUGREG_H */
index 409a649204aa7308c8936d6cc08d4479222d6885..8a0da95b4fc50e290187fd3bf3eb05b161fdf955 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_DELAY_H
-#define _ASM_X86_DELAY_H
+#ifndef ASM_X86__DELAY_H
+#define ASM_X86__DELAY_H
 
 /*
  * Copyright (C) 1993 Linus Torvalds
@@ -28,4 +28,4 @@ extern void __delay(unsigned long loops);
 
 void use_tsc_delay(void);
 
-#endif /* _ASM_X86_DELAY_H */
+#endif /* ASM_X86__DELAY_H */
index a44c4dc705902c6b1e76c92d71f1c68f759a0df4..b73fea54def29e1dfd0d2e95ec65f08c64b5cb49 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_DESC_H_
-#define _ASM_DESC_H_
+#ifndef ASM_X86__DESC_H
+#define ASM_X86__DESC_H
 
 #ifndef __ASSEMBLY__
 #include <asm/desc_defs.h>
@@ -397,4 +397,4 @@ static inline void set_system_gate_ist(int n, void *addr, unsigned ist)
 
 #endif /* __ASSEMBLY__ */
 
-#endif
+#endif /* ASM_X86__DESC_H */
index f7bacf357daca2be4fb7345d75deb69c6c6c0ee3..b881db664b46a27927d9febc4f16e39e24227d49 100644 (file)
@@ -1,6 +1,6 @@
 /* Written 2000 by Andi Kleen */
-#ifndef __ARCH_DESC_DEFS_H
-#define __ARCH_DESC_DEFS_H
+#ifndef ASM_X86__DESC_DEFS_H
+#define ASM_X86__DESC_DEFS_H
 
 /*
  * Segment descriptor structure definitions, usable from both x86_64 and i386
@@ -92,4 +92,4 @@ struct desc_ptr {
 
 #endif /* !__ASSEMBLY__ */
 
-#endif
+#endif /* ASM_X86__DESC_DEFS_H */
index 3c034f48fdb0a12f5a3fefe1499d014b68e6f4a2..1bece04c7d9d9b829d6d51abe191ce1b8abf0da9 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_DEVICE_H
-#define _ASM_X86_DEVICE_H
+#ifndef ASM_X86__DEVICE_H
+#define ASM_X86__DEVICE_H
 
 struct dev_archdata {
 #ifdef CONFIG_ACPI
@@ -13,4 +13,4 @@ struct dma_mapping_ops *dma_ops;
 #endif
 };
 
-#endif /* _ASM_X86_DEVICE_H */
+#endif /* ASM_X86__DEVICE_H */
index 9a2d644c08efc0981dbc13b1700e81917fef7c63..f9530f23f1d6ac2e4577ec036748cbbbc4752a93 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_DIV64_H
-#define _ASM_X86_DIV64_H
+#ifndef ASM_X86__DIV64_H
+#define ASM_X86__DIV64_H
 
 #ifdef CONFIG_X86_32
 
@@ -57,4 +57,4 @@ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
 # include <asm-generic/div64.h>
 #endif /* CONFIG_X86_32 */
 
-#endif /* _ASM_X86_DIV64_H */
+#endif /* ASM_X86__DIV64_H */
index ad9cd6d49bfc9bc624747709da188301b35f5b55..5d200e78bd81e18b7e315f8f2d9660cd13c23a1d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_DMA_MAPPING_H_
-#define _ASM_DMA_MAPPING_H_
+#ifndef ASM_X86__DMA_MAPPING_H
+#define ASM_X86__DMA_MAPPING_H
 
 /*
  * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for
@@ -250,4 +250,4 @@ static inline int dma_get_cache_alignment(void)
 #define dma_is_consistent(d, h)        (1)
 
 #include <asm-generic/dma-coherent.h>
-#endif
+#endif /* ASM_X86__DMA_MAPPING_H */
index ca1098a7e58057eebe268c059a682990c6ebb7e6..c9f7a4eec5557c7ce8ee02b67af6daa6dd234062 100644 (file)
@@ -5,8 +5,8 @@
  * and John Boyd, Nov. 1992.
  */
 
-#ifndef _ASM_X86_DMA_H
-#define _ASM_X86_DMA_H
+#ifndef ASM_X86__DMA_H
+#define ASM_X86__DMA_H
 
 #include <linux/spinlock.h>    /* And spinlocks */
 #include <asm/io.h>            /* need byte IO */
@@ -315,4 +315,4 @@ extern int isa_dma_bridge_buggy;
 #define isa_dma_bridge_buggy   (0)
 #endif
 
-#endif /* _ASM_X86_DMA_H */
+#endif /* ASM_X86__DMA_H */
index 58a86571fe0f8451df8800bd87b218e2be028886..1cff6fe81fa5cb9d4f20954fca9e192cd99419a9 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_DMI_H
-#define _ASM_X86_DMI_H
+#ifndef ASM_X86__DMI_H
+#define ASM_X86__DMI_H
 
 #include <asm/io.h>
 
@@ -23,4 +23,4 @@ static inline void *dmi_alloc(unsigned len)
 #define dmi_ioremap early_ioremap
 #define dmi_iounmap early_iounmap
 
-#endif
+#endif /* ASM_X86__DMI_H */
index 7881368142faaad53fe374c60aff964a69549770..6b27c686fa10f43046cd3fa123a365f408941080 100644 (file)
@@ -17,8 +17,8 @@
  * Markus Metzger <markus.t.metzger@intel.com>, Dec 2007
  */
 
-#ifndef _ASM_X86_DS_H
-#define _ASM_X86_DS_H
+#ifndef ASM_X86__DS_H
+#define ASM_X86__DS_H
 
 #include <linux/types.h>
 #include <linux/init.h>
@@ -69,4 +69,4 @@ extern int ds_write_bts(void *, const struct bts_struct *);
 extern unsigned long ds_debugctl_mask(void);
 extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *c);
 
-#endif /* _ASM_X86_DS_H */
+#endif /* ASM_X86__DS_H */
index 738bb9fb3e53c86ddb40119158b1b88307a5ab35..21d1bc32ad7c37ee7fa0213b2af692d73be0157a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _DWARF2_H
-#define _DWARF2_H
+#ifndef ASM_X86__DWARF2_H
+#define ASM_X86__DWARF2_H
 
 #ifndef __ASSEMBLY__
 #warning "asm/dwarf2.h should be only included in pure assembly files"
@@ -58,4 +58,4 @@
 
 #endif
 
-#endif
+#endif /* ASM_X86__DWARF2_H */
index 213d1ed3d415846ce2433360fe6815453769d816..f52daf176bcbba7c25a04677153bd0429a402050 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_E820_H
-#define __ASM_E820_H
+#ifndef ASM_X86__E820_H
+#define ASM_X86__E820_H
 #define E820MAP        0x2d0           /* our map */
 #define E820MAX        128             /* number of entries in E820MAP */
 
@@ -141,4 +141,4 @@ extern char *memory_setup(void);
 #define HIGH_MEMORY    (1024*1024)
 #endif /* __KERNEL__ */
 
-#endif  /* __ASM_E820_H */
+#endif /* ASM_X86__E820_H */
index a8088f63a30e4a58cfd50dde612e7da94843b3d0..9493c5b27bbdb4584bc60ff98b4fae0fd2dfc54f 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_EDAC_H
-#define _ASM_X86_EDAC_H
+#ifndef ASM_X86__EDAC_H
+#define ASM_X86__EDAC_H
 
 /* ECC atomic, DMA, SMP and interrupt safe scrub function */
 
@@ -15,4 +15,4 @@ static inline void atomic_scrub(void *va, u32 size)
                asm volatile("lock; addl $0, %0"::"m" (*virt_addr));
 }
 
-#endif
+#endif /* ASM_X86__EDAC_H */
index d4f2b0abe9294eefce100885a7c342bea885d0c5..ed2de22e87050089bb8a8c02fb85bc0a204d2141 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_EFI_H
-#define _ASM_X86_EFI_H
+#ifndef ASM_X86__EFI_H
+#define ASM_X86__EFI_H
 
 #ifdef CONFIG_X86_32
 
@@ -94,4 +94,4 @@ extern void efi_reserve_early(void);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
 
-#endif
+#endif /* ASM_X86__EFI_H */
index 7be4733c793e58c404fbab54d3c34e2e05ff8aa0..cd678b2d6a7413069cb8bdd115574f45a1c98317 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_ELF_H
-#define _ASM_X86_ELF_H
+#ifndef ASM_X86__ELF_H
+#define ASM_X86__ELF_H
 
 /*
  * ELF register definitions..
@@ -332,4 +332,4 @@ extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
-#endif
+#endif /* ASM_X86__ELF_H */
index 8e6aef19f8f02ce8be4edf1cf346ac9b257aaa77..190d0d8b71e330e35d1b0da257ab38132f218db3 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
+#ifndef ASM_X86__EMERGENCY_RESTART_H
+#define ASM_X86__EMERGENCY_RESTART_H
 
 enum reboot_type {
        BOOT_TRIPLE = 't',
@@ -15,4 +15,4 @@ extern enum reboot_type reboot_type;
 
 extern void machine_emergency_restart(void);
 
-#endif /* _ASM_EMERGENCY_RESTART_H */
+#endif /* ASM_X86__EMERGENCY_RESTART_H */
similarity index 92%
rename from include/asm-x86/mach-es7000/mach_apic.h
rename to include/asm-x86/es7000/apic.h
index 0a3fdf93067253e448ffa6a39ca8bcc0d1c0ed90..bd2c44d1f7ac356f6e09a277763b9d1d585454c2 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_APIC_H
-#define __ASM_MACH_APIC_H
+#ifndef __ASM_ES7000_APIC_H
+#define __ASM_ES7000_APIC_H
 
 #define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu)
 #define esr_disable (1)
@@ -10,7 +10,7 @@ static inline int apic_id_registered(void)
 }
 
 static inline cpumask_t target_cpus(void)
-{ 
+{
 #if defined CONFIG_ES7000_CLUSTERED_APIC
        return CPU_MASK_ALL;
 #else
@@ -23,24 +23,24 @@ static inline cpumask_t target_cpus(void)
 #define APIC_DFR_VALUE         (APIC_DFR_CLUSTER)
 #define INT_DELIVERY_MODE      (dest_LowestPrio)
 #define INT_DEST_MODE          (1)    /* logical delivery broadcast to all procs */
-#define NO_BALANCE_IRQ                 (1)
+#define NO_BALANCE_IRQ         (1)
 #undef  WAKE_SECONDARY_VIA_INIT
 #define WAKE_SECONDARY_VIA_MIP
 #else
 #define APIC_DFR_VALUE         (APIC_DFR_FLAT)
 #define INT_DELIVERY_MODE      (dest_Fixed)
 #define INT_DEST_MODE          (0)    /* phys delivery to target procs */
-#define NO_BALANCE_IRQ                 (0)
+#define NO_BALANCE_IRQ         (0)
 #undef  APIC_DEST_LOGICAL
 #define APIC_DEST_LOGICAL      0x0
 #define WAKE_SECONDARY_VIA_INIT
 #endif
 
 static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
-{ 
+{
        return 0;
-} 
-static inline unsigned long check_apicid_present(int bit) 
+}
+static inline unsigned long check_apicid_present(int bit)
 {
        return physid_isset(bit, phys_cpu_present_map);
 }
@@ -80,7 +80,7 @@ static inline void setup_apic_routing(void)
 {
        int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id());
        printk("Enabling APIC mode:  %s.  Using %d I/O APICs, target cpus %lx\n",
-               (apic_version[apic] == 0x14) ? 
+               (apic_version[apic] == 0x14) ?
                "Physical Cluster" : "Logical Cluster", nr_ioapics, cpus_addr(TARGET_CPUS)[0]);
 }
 
@@ -141,7 +141,7 @@ static inline void setup_portio_remap(void)
 extern unsigned int boot_cpu_physical_apicid;
 static inline int check_phys_apicid_present(int cpu_physical_apicid)
 {
-       boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+       boot_cpu_physical_apicid = read_apic_id();
        return (1);
 }
 
@@ -150,7 +150,7 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
        int num_bits_set;
        int cpus_found = 0;
        int cpu;
-       int apicid;     
+       int apicid;
 
        num_bits_set = cpus_weight(cpumask);
        /* Return id to all */
@@ -160,16 +160,16 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
 #else
                return cpu_to_logical_apicid(0);
 #endif
-       /* 
-        * The cpus in the mask must all be on the apic cluster.  If are not 
-        * on the same apicid cluster return default value of TARGET_CPUS. 
+       /*
+        * The cpus in the mask must all be on the apic cluster.  If are not
+        * on the same apicid cluster return default value of TARGET_CPUS.
         */
        cpu = first_cpu(cpumask);
        apicid = cpu_to_logical_apicid(cpu);
        while (cpus_found < num_bits_set) {
                if (cpu_isset(cpu, cpumask)) {
                        int new_apicid = cpu_to_logical_apicid(cpu);
-                       if (apicid_cluster(apicid) != 
+                       if (apicid_cluster(apicid) !=
                                        apicid_cluster(new_apicid)){
                                printk ("%s: Not a valid mask!\n",__FUNCTION__);
 #if defined CONFIG_ES7000_CLUSTERED_APIC
@@ -191,4 +191,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
        return cpuid_apic >> index_msb;
 }
 
-#endif /* __ASM_MACH_APIC_H */
+#endif /* __ASM_ES7000_APIC_H */
diff --git a/include/asm-x86/es7000/apicdef.h b/include/asm-x86/es7000/apicdef.h
new file mode 100644 (file)
index 0000000..8b234a3
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __ASM_ES7000_APICDEF_H
+#define __ASM_ES7000_APICDEF_H
+
+#define                APIC_ID_MASK            (0xFF<<24)
+
+static inline unsigned get_apic_id(unsigned long x)
+{
+       return (((x)>>24)&0xFF);
+}
+
+#define                GET_APIC_ID(x)  get_apic_id(x)
+
+#endif
similarity index 83%
rename from include/asm-x86/mach-es7000/mach_ipi.h
rename to include/asm-x86/es7000/ipi.h
index 5e61bd220b06c3b8b5f0a816c02d5ecc592e7145..632a955fcc0a937b870f4be05322943928ccc754 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_IPI_H
-#define __ASM_MACH_IPI_H
+#ifndef __ASM_ES7000_IPI_H
+#define __ASM_ES7000_IPI_H
 
 void send_IPI_mask_sequence(cpumask_t mask, int vector);
 
@@ -21,4 +21,4 @@ static inline void send_IPI_all(int vector)
        send_IPI_mask(cpu_online_map, vector);
 }
 
-#endif /* __ASM_MACH_IPI_H */
+#endif /* __ASM_ES7000_IPI_H */
similarity index 91%
rename from include/asm-x86/mach-es7000/mach_mpparse.h
rename to include/asm-x86/es7000/mpparse.h
index ef26d3523625451c38eeaded73228869cf737a2b..7b5c889d8e7d52bab6e7e0bd233c519940addc76 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_MPPARSE_H
-#define __ASM_MACH_MPPARSE_H
+#ifndef __ASM_ES7000_MPPARSE_H
+#define __ASM_ES7000_MPPARSE_H
 
 #include <linux/acpi.h>
 
similarity index 95%
rename from include/asm-x86/mach-es7000/mach_wakecpu.h
rename to include/asm-x86/es7000/wakecpu.h
index 84ff58314501cfa3c83cf4a7024ad19ec00f9fa9..3ffc5a7bf6677e54bb1ec2e1ff53574c63b83d47 100644 (file)
@@ -1,7 +1,7 @@
-#ifndef __ASM_MACH_WAKECPU_H
-#define __ASM_MACH_WAKECPU_H
+#ifndef __ASM_ES7000_WAKECPU_H
+#define __ASM_ES7000_WAKECPU_H
 
-/* 
+/*
  * This file copes with machines that wakeup secondary CPUs by the
  * INIT, INIT, STARTUP sequence.
  */
index 53018464aea653a407dc32e6be3d95ac14230306..aca38dbd9a644981541ef3cedeaea57d373d8d2c 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_FB_H
-#define _ASM_X86_FB_H
+#ifndef ASM_X86__FB_H
+#define ASM_X86__FB_H
 
 #include <linux/fb.h>
 #include <linux/fs.h>
@@ -18,4 +18,4 @@ extern int fb_is_primary_device(struct fb_info *info);
 static inline int fb_is_primary_device(struct fb_info *info) { return 0; }
 #endif
 
-#endif /* _ASM_X86_FB_H */
+#endif /* ASM_X86__FB_H */
index 44d4f82173496d2984b9c6612c4d4fe48341a146..78e33a1bc591ea67357cc8bee1efdeb4d75463e6 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_FIXMAP_H
-#define _ASM_FIXMAP_H
+#ifndef ASM_X86__FIXMAP_H
+#define ASM_X86__FIXMAP_H
 
 #ifdef CONFIG_X86_32
 # include "fixmap_32.h"
@@ -65,4 +65,4 @@ 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
+#endif /* ASM_X86__FIXMAP_H */
index f1ac2b2167d7fdf0ba27c450d2c688f05c3b9e02..784e3e759866cc0025b4dd4e9af77aeedddcdd1d 100644 (file)
@@ -10,8 +10,8 @@
  * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
  */
 
-#ifndef _ASM_FIXMAP_32_H
-#define _ASM_FIXMAP_32_H
+#ifndef ASM_X86__FIXMAP_32_H
+#define ASM_X86__FIXMAP_32_H
 
 
 /* used by vmalloc.c, vsyscall.lds.S.
@@ -120,4 +120,4 @@ extern void reserve_top_address(unsigned long reserve);
 #define FIXADDR_BOOT_START     (FIXADDR_TOP - __FIXADDR_BOOT_SIZE)
 
 #endif /* !__ASSEMBLY__ */
-#endif
+#endif /* ASM_X86__FIXMAP_32_H */
index 00f3d74a0524d71e77bfb4730a8b6c13f38b052f..dafb24bc0424efd4b94ed18ae2ce5e1dcf4d0260 100644 (file)
@@ -8,8 +8,8 @@
  * Copyright (C) 1998 Ingo Molnar
  */
 
-#ifndef _ASM_FIXMAP_64_H
-#define _ASM_FIXMAP_64_H
+#ifndef ASM_X86__FIXMAP_64_H
+#define ASM_X86__FIXMAP_64_H
 
 #include <linux/kernel.h>
 #include <asm/acpi.h>
@@ -80,4 +80,4 @@ enum fixed_addresses {
 #define FIXADDR_USER_START     ((unsigned long)VSYSCALL32_VSYSCALL)
 #define FIXADDR_USER_END       (FIXADDR_USER_START + PAGE_SIZE)
 
-#endif
+#endif /* ASM_X86__FIXMAP_64_H */
index dbe82a5c5eacde33f9cdf3791dfe159228f151b6..7d83a3a83e3772ed54b5e0464c94aa8506421038 100644 (file)
@@ -7,8 +7,8 @@
  *
  * Copyright (C) 1995
  */
-#ifndef _ASM_X86_FLOPPY_H
-#define _ASM_X86_FLOPPY_H
+#ifndef ASM_X86__FLOPPY_H
+#define ASM_X86__FLOPPY_H
 
 #include <linux/vmalloc.h>
 
@@ -278,4 +278,4 @@ static int FDC2 = -1;
 
 #define EXTRA_FLOPPY_PARAMS
 
-#endif /* _ASM_X86_FLOPPY_H */
+#endif /* ASM_X86__FLOPPY_H */
index 5c68b32ee1c81c28a51392303f767f05cf9ae5f3..be0e004ad148123fc5f4b85e2c5a6c2ce8569aea 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_FTRACE
-#define _ASM_X86_FTRACE
+#ifndef ASM_X86__FTRACE_H
+#define ASM_X86__FTRACE_H
 
 #ifdef CONFIG_FTRACE
 #define MCOUNT_ADDR            ((long)(mcount))
@@ -11,4 +11,4 @@ extern void mcount(void);
 
 #endif /* CONFIG_FTRACE */
 
-#endif /* _ASM_X86_FTRACE */
+#endif /* ASM_X86__FTRACE_H */
index e7a76b37b333cc8b40295d7379f8cbb46b241a29..45dc24d841865eb3d3e2b3ee374f5c7c50bb5719 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_FUTEX_H
-#define _ASM_X86_FUTEX_H
+#ifndef ASM_X86__FUTEX_H
+#define ASM_X86__FUTEX_H
 
 #ifdef __KERNEL__
 
@@ -137,4 +137,4 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
 }
 
 #endif
-#endif
+#endif /* ASM_X86__FUTEX_H */
index 3f62a83887f32c21c0919dd5c255847a8e6c2740..07f44584414636fac2a80041f4334df7b542984e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X8664_GART_H
-#define _ASM_X8664_GART_H 1
+#ifndef ASM_X86__GART_H
+#define ASM_X86__GART_H
 
 #include <asm/e820.h>
 
@@ -68,4 +68,4 @@ static inline int aperture_valid(u64 aper_base, u32 aper_size, u32 min_size)
        return 1;
 }
 
-#endif
+#endif /* ASM_X86__GART_H */
index b02ea6e17de8b6a097c722f28d2c726f5e39514d..4904c672e4f61cada1b855e14d208f9e93fb4a24 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_GENAPIC_H
-#define _ASM_GENAPIC_H 1
+#ifndef ASM_X86__GENAPIC_32_H
+#define ASM_X86__GENAPIC_32_H
 
 #include <asm/mpspec.h>
 
@@ -120,4 +120,4 @@ enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC};
 #define uv_wakeup_secondary(a, b)      1
 
 
-#endif
+#endif /* ASM_X86__GENAPIC_32_H */
index 0f8504627c41ce8c6d9f168e8ff038a8d15c3d12..128b9ec2d6f2ce77f7a2fe449cbb7ff83b796d00 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_GENAPIC_H
-#define _ASM_GENAPIC_H 1
+#ifndef ASM_X86__GENAPIC_64_H
+#define ASM_X86__GENAPIC_64_H
 
 /*
  * Copyright 2004 James Cleverdon, IBM.
@@ -14,6 +14,7 @@
 
 struct genapic {
        char *name;
+       int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
        u32 int_delivery_mode;
        u32 int_dest_mode;
        int (*apic_id_registered)(void);
@@ -24,17 +25,24 @@ struct genapic {
        void (*send_IPI_mask)(cpumask_t mask, int vector);
        void (*send_IPI_allbutself)(int vector);
        void (*send_IPI_all)(int vector);
+       void (*send_IPI_self)(int vector);
        /* */
        unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask);
        unsigned int (*phys_pkg_id)(int index_msb);
+       unsigned int (*get_apic_id)(unsigned long x);
+       unsigned long (*set_apic_id)(unsigned int id);
+       unsigned long apic_id_mask;
 };
 
 extern struct genapic *genapic;
 
 extern struct genapic apic_flat;
 extern struct genapic apic_physflat;
+extern struct genapic apic_x2apic_cluster;
+extern struct genapic apic_x2apic_phys;
 extern int acpi_madt_oem_check(char *, char *);
 
+extern void apic_send_IPI_self(int vector);
 enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC};
 extern enum uv_system_type get_uv_system_type(void);
 extern int is_uv_system(void);
@@ -46,4 +54,4 @@ extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip);
 
 extern void setup_apic_routing(void);
 
-#endif
+#endif /* ASM_X86__GENAPIC_64_H */
index bb06027fc83e557e006cd3c18e7976ff08f07745..1ef738e01a0696de4d3f294aab2959559935e927 100644 (file)
@@ -7,8 +7,8 @@
  * as published by the Free Software Foundation.
  */
 
-#ifndef _ASM_GEODE_H_
-#define _ASM_GEODE_H_
+#ifndef ASM_X86__GEODE_H
+#define ASM_X86__GEODE_H
 
 #include <asm/processor.h>
 #include <linux/io.h>
@@ -249,4 +249,4 @@ extern int __init mfgpt_timer_setup(void);
 static inline int mfgpt_timer_setup(void) { return 0; }
 #endif
 
-#endif
+#endif /* ASM_X86__GEODE_H */
index c4c91b37c104810433f074c396ca3bbc0e69c701..497fb980d96245c72689ee3bd0eb630cf0c729a7 100644 (file)
@@ -53,4 +53,4 @@ static inline int irq_to_gpio(unsigned int irq)
 
 #endif /* CONFIG_GPIOLIB */
 
-#endif /* _ASM_I386_GPIO_H */
+#endif /* ASM_X86__GPIO_H */
index 4f85f0f4b5631699e21f36016bb88ebe9b51a911..700fe230d9190dba5237d838581ec58485f793a7 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_HARDIRQ_H
-#define __ASM_HARDIRQ_H
+#ifndef ASM_X86__HARDIRQ_32_H
+#define ASM_X86__HARDIRQ_32_H
 
 #include <linux/threads.h>
 #include <linux/irq.h>
@@ -25,4 +25,4 @@ DECLARE_PER_CPU(irq_cpustat_t, irq_stat);
 void ack_bad_irq(unsigned int irq);
 #include <linux/irq_cpustat.h>
 
-#endif /* __ASM_HARDIRQ_H */
+#endif /* ASM_X86__HARDIRQ_32_H */
index 95d5e090ed89eb48d80a6c8b679db973c059d701..f8bd2919a8ce88bcb98d6b7f24f51ecfda429fcd 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_HARDIRQ_H
-#define __ASM_HARDIRQ_H
+#ifndef ASM_X86__HARDIRQ_64_H
+#define ASM_X86__HARDIRQ_64_H
 
 #include <linux/threads.h>
 #include <linux/irq.h>
@@ -20,4 +20,4 @@
 
 extern void ack_bad_irq(unsigned int irq);
 
-#endif /* __ASM_HARDIRQ_H */
+#endif /* ASM_X86__HARDIRQ_64_H */
index 4514b16cc7236b447444b30caf26c1a75196f498..bc3f6a280316d5c33f41f9f48f70606e3f096021 100644 (file)
@@ -15,8 +15,8 @@
  * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
  */
 
-#ifndef _ASM_HIGHMEM_H
-#define _ASM_HIGHMEM_H
+#ifndef ASM_X86__HIGHMEM_H
+#define ASM_X86__HIGHMEM_H
 
 #ifdef __KERNEL__
 
@@ -79,4 +79,4 @@ extern void add_highpages_with_active_regions(int nid, unsigned long start_pfn,
 
 #endif /* __KERNEL__ */
 
-#endif /* _ASM_HIGHMEM_H */
+#endif /* ASM_X86__HIGHMEM_H */
index 82f1ac641bd73214115fe7baff23e35153cfd5f0..cbbbb6d4dd32bb838462864da48b26b1becbcd2d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef ASM_X86_HPET_H
-#define ASM_X86_HPET_H
+#ifndef ASM_X86__HPET_H
+#define ASM_X86__HPET_H
 
 #ifdef CONFIG_HPET_TIMER
 
@@ -90,4 +90,4 @@ static inline int is_hpet_enabled(void) { return 0; }
 #define hpet_readl(a) 0
 
 #endif
-#endif /* ASM_X86_HPET_H */
+#endif /* ASM_X86__HPET_H */
index 439a9acc132d10f77b469fc24b250f3acc2f51d9..0b7ec5dc08840df634deb5151e35279500a49577 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_HUGETLB_H
-#define _ASM_X86_HUGETLB_H
+#ifndef ASM_X86__HUGETLB_H
+#define ASM_X86__HUGETLB_H
 
 #include <asm/page.h>
 
@@ -90,4 +90,4 @@ static inline void arch_release_hugepage(struct page *page)
 {
 }
 
-#endif /* _ASM_X86_HUGETLB_H */
+#endif /* ASM_X86__HUGETLB_H */
index 91e368893ccf0134cf98f478252ba4fe68c70162..278571a64c0e5836948402d61a1683cd54d9064a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_HW_IRQ_H
-#define _ASM_HW_IRQ_H
+#ifndef ASM_X86__HW_IRQ_H
+#define ASM_X86__HW_IRQ_H
 
 /*
  * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
@@ -73,7 +73,9 @@ extern void enable_IO_APIC(void);
 #endif
 
 /* IPI functions */
+#ifdef CONFIG_X86_32
 extern void send_IPI_self(int vector);
+#endif
 extern void send_IPI(int dest, int vector);
 
 /* Statistics */
@@ -132,4 +134,4 @@ static inline void __setup_vector_irq(int cpu) {}
 
 #endif /* !ASSEMBLY_ */
 
-#endif
+#endif /* ASM_X86__HW_IRQ_H */
index d2bbd238b3e1718e261904d1a1fd14dbf6703175..cc011a3bc1c280a1b7fb44b8cce834100c675d37 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef ASM_HYPERTRANSPORT_H
-#define ASM_HYPERTRANSPORT_H
+#ifndef ASM_X86__HYPERTRANSPORT_H
+#define ASM_X86__HYPERTRANSPORT_H
 
 /*
  * Constants for x86 Hypertransport Interrupts.
@@ -42,4 +42,4 @@
 #define HT_IRQ_HIGH_DEST_ID(v)                                         \
        ((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK)
 
-#endif /* ASM_HYPERTRANSPORT_H */
+#endif /* ASM_X86__HYPERTRANSPORT_H */
index b1733601df951353602a409880c43cb16d8299a2..1ecdc3ed96e4ecf156c83cae583ad2779d96f8b9 100644 (file)
@@ -7,12 +7,13 @@
  * x86-64 work by Andi Kleen 2002
  */
 
-#ifndef _ASM_X86_I387_H
-#define _ASM_X86_I387_H
+#ifndef ASM_X86__I387_H
+#define ASM_X86__I387_H
 
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/regset.h>
+#include <linux/hardirq.h>
 #include <asm/asm.h>
 #include <asm/processor.h>
 #include <asm/sigcontext.h>
@@ -63,8 +64,6 @@ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
 #else
                     : [fx] "cdaSDb" (fx), "m" (*fx), "0" (0));
 #endif
-       if (unlikely(err))
-               init_fpu(current);
        return err;
 }
 
@@ -237,6 +236,37 @@ static inline void kernel_fpu_end(void)
        preempt_enable();
 }
 
+/*
+ * Some instructions like VIA's padlock instructions generate a spurious
+ * DNA fault but don't modify SSE registers. And these instructions
+ * get used from interrupt context aswell. To prevent these kernel instructions
+ * in interrupt context interact wrongly with other user/kernel fpu usage, we
+ * should use them only in the context of irq_ts_save/restore()
+ */
+static inline int irq_ts_save(void)
+{
+       /*
+        * If we are in process context, we are ok to take a spurious DNA fault.
+        * Otherwise, doing clts() in process context require pre-emption to
+        * be disabled or some heavy lifting like kernel_fpu_begin()
+        */
+       if (!in_interrupt())
+               return 0;
+
+       if (read_cr0() & X86_CR0_TS) {
+               clts();
+               return 1;
+       }
+
+       return 0;
+}
+
+static inline void irq_ts_restore(int TS_state)
+{
+       if (TS_state)
+               stts();
+}
+
 #ifdef CONFIG_X86_64
 
 static inline void save_init_fpu(struct task_struct *tsk)
@@ -307,4 +337,4 @@ static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk)
        }
 }
 
-#endif /* _ASM_X86_I387_H */
+#endif /* ASM_X86__I387_H */
index b51c0487fc41d6aec43c7db474e80abd0330d50d..15a5b530044e85a56361f29c38ffd7eb75d1b38e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_I8253_H__
-#define __ASM_I8253_H__
+#ifndef ASM_X86__I8253_H
+#define ASM_X86__I8253_H
 
 /* i8253A PIT registers */
 #define PIT_MODE               0x43
@@ -15,4 +15,4 @@ extern void setup_pit_timer(void);
 #define inb_pit                inb_p
 #define outb_pit       outb_p
 
-#endif /* __ASM_I8253_H__ */
+#endif /* ASM_X86__I8253_H */
index 2f98df91f1f2bef9e7fc7bc47b3a42bbe14403d3..23c1b3baaecd09284a9ff06b5f0375f8d1cf2e86 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_I8259_H__
-#define __ASM_I8259_H__
+#ifndef ASM_X86__I8259_H
+#define ASM_X86__I8259_H
 
 #include <linux/delay.h>
 
@@ -57,4 +57,7 @@ static inline void outb_pic(unsigned char value, unsigned int port)
 
 extern struct irq_chip i8259A_chip;
 
-#endif /* __ASM_I8259_H__ */
+extern void mask_8259A(void);
+extern void unmask_8259A(void);
+
+#endif /* ASM_X86__I8259_H */
index 55d3abe5276f677c43b1840f3503c783b86217c8..f932f7ad51ddb1c11e6c121c2dd2021a60c8abf2 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_64_IA32_H
-#define _ASM_X86_64_IA32_H
+#ifndef ASM_X86__IA32_H
+#define ASM_X86__IA32_H
 
 
 #ifdef CONFIG_IA32_EMULATION
@@ -167,4 +167,4 @@ extern void ia32_pick_mmap_layout(struct mm_struct *mm);
 
 #endif /* !CONFIG_IA32_SUPPORT */
 
-#endif
+#endif /* ASM_X86__IA32_H */
index 61cea9e7c5c1b499dc67395b3d61ea18d54fee3f..dbd887d8a5a5846183fcd966feafbc73fedf3f2d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_64_IA32_UNISTD_H_
-#define _ASM_X86_64_IA32_UNISTD_H_
+#ifndef ASM_X86__IA32_UNISTD_H
+#define ASM_X86__IA32_UNISTD_H
 
 /*
  * This file contains the system call numbers of the ia32 port,
@@ -15,4 +15,4 @@
 #define __NR_ia32_sigreturn    119
 #define __NR_ia32_rt_sigreturn 173
 
-#endif /* _ASM_X86_64_IA32_UNISTD_H_ */
+#endif /* ASM_X86__IA32_UNISTD_H */
index d240e5b30a45d198acd26cf251c34930338d4e37..dc9c7944847baf227806d9ce7130497c860d60ec 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_64_IDLE_H
-#define _ASM_X86_64_IDLE_H 1
+#ifndef ASM_X86__IDLE_H
+#define ASM_X86__IDLE_H
 
 #define IDLE_START 1
 #define IDLE_END 2
@@ -10,4 +10,4 @@ void idle_notifier_register(struct notifier_block *n);
 void enter_idle(void);
 void exit_idle(void);
 
-#endif
+#endif /* ASM_X86__IDLE_H */
index fa0fd068bc2e29aeaaad694db8c0e570c43c0df5..07c03c6c9a169cdb5eeeab1d840f1a61cef2052e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_INTEL_ARCH_PERFMON_H
-#define _ASM_X86_INTEL_ARCH_PERFMON_H
+#ifndef ASM_X86__INTEL_ARCH_PERFMON_H
+#define ASM_X86__INTEL_ARCH_PERFMON_H
 
 #define MSR_ARCH_PERFMON_PERFCTR0              0xc1
 #define MSR_ARCH_PERFMON_PERFCTR1              0xc2
@@ -28,4 +28,4 @@ union cpuid10_eax {
        unsigned int full;
 };
 
-#endif /* _ASM_X86_INTEL_ARCH_PERFMON_H */
+#endif /* ASM_X86__INTEL_ARCH_PERFMON_H */
index a145210ac16b7ae20c5c23dc511c01c72fe0e32d..25417d6c5c6216efc406f41cc625a2137db17f60 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_IO_H
-#define _ASM_X86_IO_H
+#ifndef ASM_X86__IO_H
+#define ASM_X86__IO_H
 
 #define ARCH_HAS_IOREMAP_WC
 
@@ -101,4 +101,4 @@ extern void early_iounmap(void *addr, unsigned long size);
 extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
 
 
-#endif /* _ASM_X86_IO_H */
+#endif /* ASM_X86__IO_H */
index e876d89ac15618f88ea4b624de64c6b1fc27e9cd..4f7d878bda1819a51541b67bda6dc7f4c53ac248 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_IO_H
-#define _ASM_IO_H
+#ifndef ASM_X86__IO_32_H
+#define ASM_X86__IO_32_H
 
 #include <linux/string.h>
 #include <linux/compiler.h>
@@ -281,4 +281,4 @@ BUILDIO(b, b, char)
 BUILDIO(w, w, short)
 BUILDIO(l, , int)
 
-#endif
+#endif /* ASM_X86__IO_32_H */
index 080482acaffc28e934a89a3f5e9f97fe57f3f693..64429e9431a8aef1089c25c8c00c18b64cd93663 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_IO_H
-#define _ASM_IO_H
+#ifndef ASM_X86__IO_64_H
+#define ASM_X86__IO_64_H
 
 
 /*
@@ -244,4 +244,4 @@ void memset_io(volatile void __iomem *a, int b, size_t c);
 
 #endif /* __KERNEL__ */
 
-#endif
+#endif /* ASM_X86__IO_64_H */
index 14f82bbcb5fd6ee5d09f05be363651258ff4e9bb..8ec68a50cf103b3779da806b391978fb27fcdc2c 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_IO_APIC_H
-#define __ASM_IO_APIC_H
+#ifndef ASM_X86__IO_APIC_H
+#define ASM_X86__IO_APIC_H
 
 #include <linux/types.h>
 #include <asm/mpspec.h>
@@ -107,6 +107,20 @@ struct IO_APIC_route_entry {
 
 } __attribute__ ((packed));
 
+struct IR_IO_APIC_route_entry {
+       __u64   vector          : 8,
+               zero            : 3,
+               index2          : 1,
+               delivery_status : 1,
+               polarity        : 1,
+               irr             : 1,
+               trigger         : 1,
+               mask            : 1,
+               reserved        : 31,
+               format          : 1,
+               index           : 15;
+} __attribute__ ((packed));
+
 #ifdef CONFIG_X86_IO_APIC
 
 /*
@@ -183,10 +197,16 @@ extern int io_apic_set_pci_routing(int ioapic, int pin, int irq,
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 
+#ifdef CONFIG_X86_64
+extern int save_mask_IO_APIC_setup(void);
+extern void restore_IO_APIC_setup(void);
+extern void reinit_intr_remapped_IO_APIC(int);
+#endif
+
 #else  /* !CONFIG_X86_IO_APIC */
 #define io_apic_assign_pci_irqs 0
 static const int timer_through_8259 = 0;
 static inline void ioapic_init_mappings(void) { }
 #endif
 
-#endif
+#endif /* ASM_X86__IO_APIC_H */
index c0c338bd40682e41e4699639794a301a87a3b3ae..33660351239968bd22205ed9e4b45e674bc67e96 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_IOCTLS_H
-#define _ASM_X86_IOCTLS_H
+#ifndef ASM_X86__IOCTLS_H
+#define ASM_X86__IOCTLS_H
 
 #include <asm/ioctl.h>
 
@@ -85,4 +85,4 @@
 
 #define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
 
-#endif
+#endif /* ASM_X86__IOCTLS_H */
index 5f888cc5be49a0eb87fab02d32ec050a686d0387..e86f44148c66f043cfb3a9ba9dfc1419cc2b25da 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X8664_IOMMU_H
-#define _ASM_X8664_IOMMU_H 1
+#ifndef ASM_X86__IOMMU_H
+#define ASM_X86__IOMMU_H
 
 extern void pci_iommu_shutdown(void);
 extern void no_iommu_init(void);
@@ -42,4 +42,4 @@ static inline void gart_iommu_hole_init(void)
 }
 #endif
 
-#endif
+#endif /* ASM_X86__IOMMU_H */
index ee678fd51594e5100d42e244433f3e8dc1c70690..910304fbdc8f289e7f92e37a4bd2089b540f585f 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_IPCBUF_H
-#define _ASM_X86_IPCBUF_H
+#ifndef ASM_X86__IPCBUF_H
+#define ASM_X86__IPCBUF_H
 
 /*
  * The ipc64_perm structure for x86 architecture.
@@ -25,4 +25,4 @@ struct ipc64_perm {
        unsigned long           __unused2;
 };
 
-#endif /* _ASM_X86_IPCBUF_H */
+#endif /* ASM_X86__IPCBUF_H */
index bb1c09f7a76ced4cd028d631d79a13d0171e8c2c..30a692cfaff8f1a67c827f5bd58ed73b24fad9d7 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_IPI_H
-#define __ASM_IPI_H
+#ifndef ASM_X86__IPI_H
+#define ASM_X86__IPI_H
 
 /*
  * Copyright 2004 James Cleverdon, IBM.
@@ -49,6 +49,12 @@ static inline int __prepare_ICR2(unsigned int mask)
        return SET_APIC_DEST_FIELD(mask);
 }
 
+static inline void __xapic_wait_icr_idle(void)
+{
+       while (native_apic_mem_read(APIC_ICR) & APIC_ICR_BUSY)
+               cpu_relax();
+}
+
 static inline void __send_IPI_shortcut(unsigned int shortcut, int vector,
                                       unsigned int dest)
 {
@@ -64,7 +70,7 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector,
        /*
         * Wait for idle.
         */
-       apic_wait_icr_idle();
+       __xapic_wait_icr_idle();
 
        /*
         * No need to touch the target chip field
@@ -74,7 +80,7 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector,
        /*
         * Send the IPI. The write to APIC_ICR fires this off.
         */
-       apic_write(APIC_ICR, cfg);
+       native_apic_mem_write(APIC_ICR, cfg);
 }
 
 /*
@@ -92,13 +98,13 @@ static inline void __send_IPI_dest_field(unsigned int mask, int vector,
        if (unlikely(vector == NMI_VECTOR))
                safe_apic_wait_icr_idle();
        else
-               apic_wait_icr_idle();
+               __xapic_wait_icr_idle();
 
        /*
         * prepare target chip field
         */
        cfg = __prepare_ICR2(mask);
-       apic_write(APIC_ICR2, cfg);
+       native_apic_mem_write(APIC_ICR2, cfg);
 
        /*
         * program the ICR
@@ -108,7 +114,7 @@ static inline void __send_IPI_dest_field(unsigned int mask, int vector,
        /*
         * Send the IPI. The write to APIC_ICR fires this off.
         */
-       apic_write(APIC_ICR, cfg);
+       native_apic_mem_write(APIC_ICR, cfg);
 }
 
 static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
@@ -129,4 +135,4 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
        local_irq_restore(flags);
 }
 
-#endif /* __ASM_IPI_H */
+#endif /* ASM_X86__IPI_H */
index 1a292575731745bdc9c5734adb426220eac6649c..1e5f2909c1db8c7db9330412444cafb07c0d1149 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_IRQ_H
-#define _ASM_IRQ_H
+#ifndef ASM_X86__IRQ_H
+#define ASM_X86__IRQ_H
 /*
  *     (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
  *
@@ -47,4 +47,4 @@ extern void native_init_IRQ(void);
 /* Interrupt vector management */
 extern DECLARE_BITMAP(used_vectors, NR_VECTORS);
 
-#endif /* _ASM_IRQ_H */
+#endif /* ASM_X86__IRQ_H */
index 3368b20c0b489fa04b46070d53aecaaeb8dc01e0..316a3b2588715cd0cec869c51eaa4f6774972c64 100644 (file)
@@ -4,8 +4,8 @@
  *
  * Jeremy Fitzhardinge <jeremy@goop.org>
  */
-#ifndef _ASM_I386_IRQ_REGS_H
-#define _ASM_I386_IRQ_REGS_H
+#ifndef ASM_X86__IRQ_REGS_32_H
+#define ASM_X86__IRQ_REGS_32_H
 
 #include <asm/percpu.h>
 
@@ -26,4 +26,4 @@ static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
        return old_regs;
 }
 
-#endif /* _ASM_I386_IRQ_REGS_H */
+#endif /* ASM_X86__IRQ_REGS_32_H */
diff --git a/include/asm-x86/irq_remapping.h b/include/asm-x86/irq_remapping.h
new file mode 100644 (file)
index 0000000..78242c6
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _ASM_IRQ_REMAPPING_H
+#define _ASM_IRQ_REMAPPING_H
+
+extern int x2apic;
+
+#define IRTE_DEST(dest) ((x2apic) ? dest : dest << 8)
+
+#endif
index b95d167b7fb26d8697a1d1a56b2000648b042e8b..3f4b1b6be88c35437c6da045f08c61655af8c788 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_IRQ_VECTORS_H
-#define _ASM_IRQ_VECTORS_H
+#ifndef ASM_X86__IRQ_VECTORS_H
+#define ASM_X86__IRQ_VECTORS_H
 
 #include <linux/threads.h>
 
 #define VIC_CPU_BOOT_ERRATA_CPI                (VIC_CPI_LEVEL0 + 8)
 
 
-#endif /* _ASM_IRQ_VECTORS_H */
+#endif /* ASM_X86__IRQ_VECTORS_H */
index 6ec6ceed95a718ec9d3c91f6004a459781dee74b..35a2fe9bc9212f799d3f3c2797af33d65b11eacd 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_IST_H
-#define _ASM_IST_H
+#ifndef ASM_X86__IST_H
+#define ASM_X86__IST_H
 
 /*
  * Include file for the interface to IST BIOS
@@ -31,4 +31,4 @@ struct ist_info {
 extern struct ist_info ist_info;
 
 #endif /* __KERNEL__ */
-#endif /* _ASM_IST_H */
+#endif /* ASM_X86__IST_H */
index 452e2b696ff48ef2cdf26175572dde1132a175cf..2bbaf4370a553b7aa6cff16b61c9f1f39e8b1009 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_K8_H
-#define _ASM_K8_H 1
+#ifndef ASM_X86__K8_H
+#define ASM_X86__K8_H
 
 #include <linux/pci.h>
 
@@ -12,4 +12,4 @@ extern int cache_k8_northbridges(void);
 extern void k8_flush_garts(void);
 extern int k8_scan_nodes(unsigned long start, unsigned long end);
 
-#endif
+#endif /* ASM_X86__K8_H */
index 96651bb59ba18c6f8506d985f9c98a757617a338..5ec3ad3e825c4dadfcbcff6b6f9c880f6ec02c7a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_KDEBUG_H
-#define _ASM_X86_KDEBUG_H
+#ifndef ASM_X86__KDEBUG_H
+#define ASM_X86__KDEBUG_H
 
 #include <linux/notifier.h>
 
@@ -35,4 +35,4 @@ extern void show_regs(struct pt_regs *regs);
 extern unsigned long oops_begin(void);
 extern void oops_end(unsigned long, struct pt_regs *, int signr);
 
-#endif
+#endif /* ASM_X86__KDEBUG_H */
index c0e52a14fd4dd981ee36ea66484f7f564b40bd04..17bde9552a8898dd0255d954f2fa08d23fb1b28c 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _KEXEC_H
-#define _KEXEC_H
+#ifndef ASM_X86__KEXEC_H
+#define ASM_X86__KEXEC_H
 
 #ifdef CONFIG_X86_32
 # define PA_CONTROL_PAGE       0
@@ -168,4 +168,4 @@ relocate_kernel(unsigned long indirection_page,
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* _KEXEC_H */
+#endif /* ASM_X86__KEXEC_H */
index 484c47554f3bc6e76db3eafdb5443c2cda0ba55b..83a7ee228ab13c68f8e531910d49dcb8f72f807b 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_KGDB_H_
-#define _ASM_KGDB_H_
+#ifndef ASM_X86__KGDB_H
+#define ASM_X86__KGDB_H
 
 /*
  * Copyright (C) 2001-2004 Amit S. Kale
@@ -78,4 +78,4 @@ static inline void arch_kgdb_breakpoint(void)
 #define BREAK_INSTR_SIZE       1
 #define CACHE_FLUSH_IS_SAFE    1
 
-#endif                         /* _ASM_KGDB_H_ */
+#endif /* ASM_X86__KGDB_H */
index 5f4174132a222a34d453b2fb915a0993a6e923be..89f44493e6432ad192fa65faeac1b46c93ce6eb6 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_KMAP_TYPES_H
-#define _ASM_X86_KMAP_TYPES_H
+#ifndef ASM_X86__KMAP_TYPES_H
+#define ASM_X86__KMAP_TYPES_H
 
 #if defined(CONFIG_X86_32) && defined(CONFIG_DEBUG_HIGHMEM)
 # define D(n) __KM_FENCE_##n ,
@@ -26,4 +26,4 @@ D(13) KM_TYPE_NR
 
 #undef D
 
-#endif
+#endif /* ASM_X86__KMAP_TYPES_H */
index 54980b0b38925ade9c59799f906234e313b3237c..bd8407863c13127f1ed7ce1384fce4086e135022 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_KPROBES_H
-#define _ASM_KPROBES_H
+#ifndef ASM_X86__KPROBES_H
+#define ASM_X86__KPROBES_H
 /*
  *  Kernel Probes (KProbes)
  *
@@ -94,4 +94,4 @@ static inline void restore_interrupts(struct pt_regs *regs)
 extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
                                    unsigned long val, void *data);
-#endif                         /* _ASM_KPROBES_H */
+#endif /* ASM_X86__KPROBES_H */
index 6f1840812e595f05b7d5a064412e05d7e756b1cc..78e954db1e7f60066ea2cd232bf4d38a99821e57 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __LINUX_KVM_X86_H
-#define __LINUX_KVM_X86_H
+#ifndef ASM_X86__KVM_H
+#define ASM_X86__KVM_H
 
 /*
  * KVM x86 specific structures and definitions
@@ -230,4 +230,4 @@ struct kvm_pit_state {
 #define KVM_TRC_APIC_ACCESS      (KVM_TRC_HANDLER + 0x14)
 #define KVM_TRC_TDP_FAULT        (KVM_TRC_HANDLER + 0x15)
 
-#endif
+#endif /* ASM_X86__KVM_H */
index 0f3c531146142df89075e4623c36377510c7489e..72e9a525f91a64ca5318df5e794c082135a27201 100644 (file)
@@ -1,4 +1,4 @@
-#/*
+/*
  * Kernel-based Virtual Machine driver for Linux
  *
  * This header defines architecture specific interfaces, x86 version
@@ -8,8 +8,8 @@
  *
  */
 
-#ifndef ASM_KVM_HOST_H
-#define ASM_KVM_HOST_H
+#ifndef ASM_X86__KVM_HOST_H
+#define ASM_X86__KVM_HOST_H
 
 #include <linux/types.h>
 #include <linux/mm.h>
@@ -735,4 +735,4 @@ asmlinkage void kvm_handle_fault_on_reboot(void);
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
 int kvm_age_hva(struct kvm *kvm, unsigned long hva);
 
-#endif
+#endif /* ASM_X86__KVM_HOST_H */
index 76f392146daa46304adfb404874164a7a628010d..30054fded4fbbe325271e9ca2db0424eb3ebbdde 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __X86_KVM_PARA_H
-#define __X86_KVM_PARA_H
+#ifndef ASM_X86__KVM_PARA_H
+#define ASM_X86__KVM_PARA_H
 
 /* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx.  It
  * should be used to determine that a VM is running under KVM.
@@ -144,4 +144,4 @@ static inline unsigned int kvm_arch_para_features(void)
 
 #endif
 
-#endif
+#endif /* ASM_X86__KVM_PARA_H */
index 4e8c1e48d91daf5c8e73e9d3441a73e70539c000..e2d9b030c1ac9460297c34c08a1e796b13afa85c 100644 (file)
@@ -8,8 +8,8 @@
  * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4
  */
 
-#ifndef __X86_EMULATE_H__
-#define __X86_EMULATE_H__
+#ifndef ASM_X86__KVM_X86_EMULATE_H
+#define ASM_X86__KVM_X86_EMULATE_H
 
 struct x86_emulate_ctxt;
 
@@ -181,4 +181,4 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt,
 int x86_emulate_insn(struct x86_emulate_ctxt *ctxt,
                     struct x86_emulate_ops *ops);
 
-#endif                         /* __X86_EMULATE_H__ */
+#endif /* ASM_X86__KVM_X86_EMULATE_H */
index 20c597242b53db0038fbf4efe7403b8425c7e16f..a5228504d867e68045b52f6a514b8f2130efacec 100644 (file)
@@ -3,8 +3,8 @@
  *
  * Definitions of structures used with the modify_ldt system call.
  */
-#ifndef _ASM_X86_LDT_H
-#define _ASM_X86_LDT_H
+#ifndef ASM_X86__LDT_H
+#define ASM_X86__LDT_H
 
 /* Maximum number of LDT entries supported. */
 #define LDT_ENTRIES    8192
@@ -37,4 +37,4 @@ struct user_desc {
 #define MODIFY_LDT_CONTENTS_CODE       2
 
 #endif /* !__ASSEMBLY__ */
-#endif
+#endif /* ASM_X86__LDT_H */
index be4a7247fa2b3ea44c07332bf76436d0cb6cc7df..7505e947ed2719a32a91c53a52598905a63818e4 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _X86_LGUEST_H
-#define _X86_LGUEST_H
+#ifndef ASM_X86__LGUEST_H
+#define ASM_X86__LGUEST_H
 
 #define GDT_ENTRY_LGUEST_CS    10
 #define GDT_ENTRY_LGUEST_DS    11
@@ -91,4 +91,4 @@ static inline void lguest_set_ts(void)
 
 #endif /* __ASSEMBLY__ */
 
-#endif
+#endif /* ASM_X86__LGUEST_H */
index a3241f28e34a51e469c77251200915567c8ade42..8f034ba4b53ebf1b3e6df32be9e5252ccf433f76 100644 (file)
@@ -1,6 +1,6 @@
 /* Architecture specific portion of the lguest hypercalls */
-#ifndef _X86_LGUEST_HCALL_H
-#define _X86_LGUEST_HCALL_H
+#ifndef ASM_X86__LGUEST_HCALL_H
+#define ASM_X86__LGUEST_HCALL_H
 
 #define LHCALL_FLUSH_ASYNC     0
 #define LHCALL_LGUEST_INIT     1
@@ -68,4 +68,4 @@ struct hcall_args {
 };
 
 #endif /* !__ASSEMBLY__ */
-#endif /* _I386_LGUEST_HCALL_H */
+#endif /* ASM_X86__LGUEST_HCALL_H */
index 64e444f8e85b2d9fccaf50cc78ceaa1da0654877..42d8b62ee8abe72e842c55a3c337d0e947802561 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_LINKAGE_H
-#define __ASM_LINKAGE_H
+#ifndef ASM_X86__LINKAGE_H
+#define ASM_X86__LINKAGE_H
 
 #undef notrace
 #define notrace __attribute__((no_instrument_function))
@@ -57,5 +57,5 @@
 #define __ALIGN_STR ".align 16,0x90"
 #endif
 
-#endif
+#endif /* ASM_X86__LINKAGE_H */
 
index 330a72496abd94f9eb85cce30f8ae590b1b57e18..ae91994fd6c91dc607251a31d5e2df0db6d8f6af 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ARCH_LOCAL_H
-#define _ARCH_LOCAL_H
+#ifndef ASM_X86__LOCAL_H
+#define ASM_X86__LOCAL_H
 
 #include <linux/percpu.h>
 
@@ -232,4 +232,4 @@ static inline long local_sub_return(long i, local_t *l)
 #define __cpu_local_add(i, l)  cpu_local_add((i), (l))
 #define __cpu_local_sub(i, l)  cpu_local_sub((i), (l))
 
-#endif /* _ARCH_LOCAL_H */
+#endif /* ASM_X86__LOCAL_H */
index 989f34c37d321249f838efe86d4e9c2086b42233..2aa61b54fbd576f7c353eb4738904694e0844633 100644 (file)
@@ -3,8 +3,8 @@
  *  Split out from apm.c by Osamu Tomita <tomita@cinet.co.jp>
  */
 
-#ifndef _ASM_APM_H
-#define _ASM_APM_H
+#ifndef ASM_X86__MACH_DEFAULT__APM_H
+#define ASM_X86__MACH_DEFAULT__APM_H
 
 #ifdef APM_ZERO_SEGS
 #      define APM_DO_ZERO_SEGS \
@@ -70,4 +70,4 @@ static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in,
        return error;
 }
 
-#endif /* _ASM_APM_H */
+#endif /* ASM_X86__MACH_DEFAULT__APM_H */
index f3226b9a6b823459935a4de2c5b8e82165776e57..2a330a41b3dd703fcafc3d254e3aa3f664302c0d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_APIC_H
-#define __ASM_MACH_APIC_H
+#ifndef ASM_X86__MACH_DEFAULT__MACH_APIC_H
+#define ASM_X86__MACH_DEFAULT__MACH_APIC_H
 
 #ifdef CONFIG_X86_LOCAL_APIC
 
@@ -30,6 +30,8 @@ static inline cpumask_t target_cpus(void)
 #define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid)
 #define phys_pkg_id    (genapic->phys_pkg_id)
 #define vector_allocation_domain    (genapic->vector_allocation_domain)
+#define read_apic_id()  (GET_APIC_ID(apic_read(APIC_ID)))
+#define send_IPI_self (genapic->send_IPI_self)
 extern void setup_apic_routing(void);
 #else
 #define INT_DELIVERY_MODE dest_LowestPrio
@@ -54,7 +56,7 @@ static inline void init_apic_ldr(void)
 
 static inline int apic_id_registered(void)
 {
-       return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map);
+       return physid_isset(read_apic_id(), phys_cpu_present_map);
 }
 
 static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
@@ -138,4 +140,4 @@ static inline void enable_apic_mode(void)
 }
 
 #endif /* CONFIG_X86_LOCAL_APIC */
-#endif /* __ASM_MACH_APIC_H */
+#endif /* ASM_X86__MACH_DEFAULT__MACH_APIC_H */
index e4b29ba37de604894bae11681a9236bd64c041e7..0c2d41c41b208fd0ac1762b414a13a354847448a 100644 (file)
@@ -1,12 +1,12 @@
-#ifndef __ASM_MACH_APICDEF_H
-#define __ASM_MACH_APICDEF_H
+#ifndef ASM_X86__MACH_DEFAULT__MACH_APICDEF_H
+#define ASM_X86__MACH_DEFAULT__MACH_APICDEF_H
 
 #include <asm/apic.h>
 
 #ifdef CONFIG_X86_64
-#define        APIC_ID_MASK            (0xFFu<<24)
-#define GET_APIC_ID(x)          (((x)>>24)&0xFFu)
-#define        SET_APIC_ID(x)          (((x)<<24))
+#define        APIC_ID_MASK            (genapic->apic_id_mask)
+#define GET_APIC_ID(x)         (genapic->get_apic_id(x))
+#define        SET_APIC_ID(x)          (genapic->set_apic_id(x))
 #else
 #define                APIC_ID_MASK            (0xF<<24)
 static inline unsigned get_apic_id(unsigned long x) 
@@ -21,4 +21,4 @@ static inline unsigned get_apic_id(unsigned long x)
 #define                GET_APIC_ID(x)  get_apic_id(x)
 #endif
 
-#endif
+#endif /* ASM_X86__MACH_DEFAULT__MACH_APICDEF_H */
index be323364e68f6d7522194f7b2d2941df8edd6d19..674bc7e50c356250348c5341a6aba2a9167920a1 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_IPI_H
-#define __ASM_MACH_IPI_H
+#ifndef ASM_X86__MACH_DEFAULT__MACH_IPI_H
+#define ASM_X86__MACH_DEFAULT__MACH_IPI_H
 
 /* Avoid include hell */
 #define NMI_VECTOR 0x02
@@ -61,4 +61,4 @@ static inline void send_IPI_all(int vector)
 }
 #endif
 
-#endif /* __ASM_MACH_IPI_H */
+#endif /* ASM_X86__MACH_DEFAULT__MACH_IPI_H */
index d14108505bb8905401f61ddab7f93fd34c3ce533..9c381f2815acb9752359d1538e662ff2966bc50f 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_MPPARSE_H
-#define __ASM_MACH_MPPARSE_H
+#ifndef ASM_X86__MACH_DEFAULT__MACH_MPPARSE_H
+#define ASM_X86__MACH_DEFAULT__MACH_MPPARSE_H
 
 static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, 
                char *productid)
@@ -14,4 +14,4 @@ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 }
 
 
-#endif /* __ASM_MACH_MPPARSE_H */
+#endif /* ASM_X86__MACH_DEFAULT__MACH_MPPARSE_H */
index 51c9a977593289a2c72452a0b2a44504a7353189..d77646f011f1bb1dfce06bce8b63732898490804 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_MPSPEC_H
-#define __ASM_MACH_MPSPEC_H
+#ifndef ASM_X86__MACH_DEFAULT__MACH_MPSPEC_H
+#define ASM_X86__MACH_DEFAULT__MACH_MPSPEC_H
 
 #define MAX_IRQ_SOURCES 256
 
@@ -9,4 +9,4 @@
 #define MAX_MP_BUSSES 32
 #endif
 
-#endif /* __ASM_MACH_MPSPEC_H */
+#endif /* ASM_X86__MACH_DEFAULT__MACH_MPSPEC_H */
index 4b76e536cd986307b071c8c11d2bff4c30b4112f..990b15833834bf861ceef35d810d4adaa899a84d 100644 (file)
@@ -10,8 +10,8 @@
  * directly because of the awkward 8-bit access mechanism of the 82C54
  * device.
  */
-#ifndef _MACH_TIMER_H
-#define _MACH_TIMER_H
+#ifndef ASM_X86__MACH_DEFAULT__MACH_TIMER_H
+#define ASM_X86__MACH_DEFAULT__MACH_TIMER_H
 
 #define CALIBRATE_TIME_MSEC 30 /* 30 msecs */
 #define CALIBRATE_LATCH        \
@@ -45,4 +45,4 @@ static inline void mach_countup(unsigned long *count_p)
        *count_p = count;
 }
 
-#endif /* !_MACH_TIMER_H */
+#endif /* ASM_X86__MACH_DEFAULT__MACH_TIMER_H */
index 2fe7705c0484ed074a5d0b2f9e2bf7acc88cd7cf..de9ac3f5c4ce547c2a204cac41c4010da2839fe7 100644 (file)
@@ -2,8 +2,8 @@
  *  Machine specific NMI handling for generic.
  *  Split out from traps.c by Osamu Tomita <tomita@cinet.co.jp>
  */
-#ifndef _MACH_TRAPS_H
-#define _MACH_TRAPS_H
+#ifndef ASM_X86__MACH_DEFAULT__MACH_TRAPS_H
+#define ASM_X86__MACH_DEFAULT__MACH_TRAPS_H
 
 #include <asm/mc146818rtc.h>
 
@@ -36,4 +36,4 @@ static inline void reassert_nmi(void)
                unlock_cmos();
 }
 
-#endif /* !_MACH_TRAPS_H */
+#endif /* ASM_X86__MACH_DEFAULT__MACH_TRAPS_H */
index 3ebb17893aa524d49d4bcdec543148ee7e72a326..361b810f5160a2e5a02e8ea66c365a9dc0abd0f1 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_WAKECPU_H
-#define __ASM_MACH_WAKECPU_H
+#ifndef ASM_X86__MACH_DEFAULT__MACH_WAKECPU_H
+#define ASM_X86__MACH_DEFAULT__MACH_WAKECPU_H
 
 /* 
  * This file copes with machines that wakeup secondary CPUs by the
@@ -39,4 +39,4 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
  #define inquire_remote_apic(apicid) {}
 #endif
 
-#endif /* __ASM_MACH_WAKECPU_H */
+#endif /* ASM_X86__MACH_DEFAULT__MACH_WAKECPU_H */
diff --git a/include/asm-x86/mach-es7000/mach_apicdef.h b/include/asm-x86/mach-es7000/mach_apicdef.h
deleted file mode 100644 (file)
index a58ab5a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ASM_MACH_APICDEF_H
-#define __ASM_MACH_APICDEF_H
-
-#define                APIC_ID_MASK            (0xFF<<24)
-
-static inline unsigned get_apic_id(unsigned long x) 
-{ 
-       return (((x)>>24)&0xFF);
-} 
-
-#define                GET_APIC_ID(x)  get_apic_id(x)
-
-#endif
index 5305dcb96df270f511ce44bd953fc62e2c15e489..6ce0f7786ef8bebfe8ef51414de7553c908a6fd7 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_GENERIC_GPIO_H
-#define __ASM_MACH_GENERIC_GPIO_H
+#ifndef ASM_X86__MACH_GENERIC__GPIO_H
+#define ASM_X86__MACH_GENERIC__GPIO_H
 
 int gpio_request(unsigned gpio, const char *label);
 void gpio_free(unsigned gpio);
@@ -12,4 +12,4 @@ int irq_to_gpio(unsigned irq);
 
 #include <asm-generic/gpio.h>           /* cansleep wrappers */
 
-#endif /* __ASM_MACH_GENERIC_GPIO_H */
+#endif /* ASM_X86__MACH_GENERIC__GPIO_H */
index 890ce3f5e09a7fbd89590fc7490627b0a807f986..f7870e1a220d535bbccd798dd994506c095aabe4 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_IRQ_VECTORS_LIMITS_H
-#define _ASM_IRQ_VECTORS_LIMITS_H
+#ifndef ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H
+#define ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H
 
 /*
  * For Summit or generic (i.e. installer) kernels, we have lots of I/O APICs,
@@ -11,4 +11,4 @@
 #define NR_IRQS        224
 #define NR_IRQ_VECTORS 1024
 
-#endif /* _ASM_IRQ_VECTORS_LIMITS_H */
+#endif /* ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H */
index 6eff343e12338f892693fa667ea25105f2ff7da9..5d010c6881dddc51bb9ad2a59503c79ad2837b14 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_APIC_H
-#define __ASM_MACH_APIC_H
+#ifndef ASM_X86__MACH_GENERIC__MACH_APIC_H
+#define ASM_X86__MACH_GENERIC__MACH_APIC_H
 
 #include <asm/genapic.h>
 
@@ -29,4 +29,4 @@
 
 extern void generic_bigsmp_probe(void);
 
-#endif /* __ASM_MACH_APIC_H */
+#endif /* ASM_X86__MACH_GENERIC__MACH_APIC_H */
index 28ed98972ca84a98fbdd2a38dceb8dbdb94e5ca9..1657f38b8f27e184bb930a24eb3b992eaf548bbb 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _GENAPIC_MACH_APICDEF_H
-#define _GENAPIC_MACH_APICDEF_H 1
+#ifndef ASM_X86__MACH_GENERIC__MACH_APICDEF_H
+#define ASM_X86__MACH_GENERIC__MACH_APICDEF_H
 
 #ifndef APIC_DEFINITION
 #include <asm/genapic.h>
@@ -8,4 +8,4 @@
 #define APIC_ID_MASK (genapic->apic_id_mask)
 #endif
 
-#endif
+#endif /* ASM_X86__MACH_GENERIC__MACH_APICDEF_H */
index 441b0fe3ed1d8142cb0ef503b5a58718f90b8137..f67433dbd65f9f85b549ee4e34efdf68385725f3 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _MACH_IPI_H
-#define _MACH_IPI_H 1
+#ifndef ASM_X86__MACH_GENERIC__MACH_IPI_H
+#define ASM_X86__MACH_GENERIC__MACH_IPI_H
 
 #include <asm/genapic.h>
 
@@ -7,4 +7,4 @@
 #define send_IPI_allbutself (genapic->send_IPI_allbutself)
 #define send_IPI_all (genapic->send_IPI_all)
 
-#endif
+#endif /* ASM_X86__MACH_GENERIC__MACH_IPI_H */
index 586cadbf3787ce9c98449921db1c14c942d418bc..3115564e557cfd6d6b25f6ea02bb585d17121e43 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _MACH_MPPARSE_H
-#define _MACH_MPPARSE_H 1
+#ifndef ASM_X86__MACH_GENERIC__MACH_MPPARSE_H
+#define ASM_X86__MACH_GENERIC__MACH_MPPARSE_H
 
 
 extern int mps_oem_check(struct mp_config_table *mpc, char *oem,
@@ -7,4 +7,4 @@ extern int mps_oem_check(struct mp_config_table *mpc, char *oem,
 
 extern int acpi_madt_oem_check(char *oem_id, char *oem_table_id);
 
-#endif
+#endif /* ASM_X86__MACH_GENERIC__MACH_MPPARSE_H */
index c83c120be538504f5139228bc53182e3040f43ea..6061b153613e32ec75d0cf983091aa13dbea31d5 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_MPSPEC_H
-#define __ASM_MACH_MPSPEC_H
+#ifndef ASM_X86__MACH_GENERIC__MACH_MPSPEC_H
+#define ASM_X86__MACH_GENERIC__MACH_MPSPEC_H
 
 #define MAX_IRQ_SOURCES 256
 
@@ -9,4 +9,4 @@
 
 extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
                                char *productid);
-#endif /* __ASM_MACH_MPSPEC_H */
+#endif /* ASM_X86__MACH_GENERIC__MACH_MPSPEC_H */
index acce0b7d397bb2465ee89beb6e8a7d817bccbc7a..6184561980f2ff68e66a8049ba2b9f8d37185607 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _RDC321X_GPIO_H
-#define _RDC321X_GPIO_H
+#ifndef ASM_X86__MACH_RDC321X__GPIO_H
+#define ASM_X86__MACH_RDC321X__GPIO_H
 
 extern int rdc_gpio_get_value(unsigned gpio);
 extern void rdc_gpio_set_value(unsigned gpio, int value);
@@ -54,4 +54,4 @@ static inline int irq_to_gpio(unsigned irq)
 /* For cansleep */
 #include <asm-generic/gpio.h>
 
-#endif /* _RDC321X_GPIO_H_ */
+#endif /* ASM_X86__MACH_RDC321X__GPIO_H */
diff --git a/include/asm-x86/mach-summit/mach_apicdef.h b/include/asm-x86/mach-summit/mach_apicdef.h
deleted file mode 100644 (file)
index a58ab5a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ASM_MACH_APICDEF_H
-#define __ASM_MACH_APICDEF_H
-
-#define                APIC_ID_MASK            (0xFF<<24)
-
-static inline unsigned get_apic_id(unsigned long x) 
-{ 
-       return (((x)>>24)&0xFF);
-} 
-
-#define                GET_APIC_ID(x)  get_apic_id(x)
-
-#endif
index 9bf4ae93ab10b3a549efaac717fcdce0f81a158d..5768d8e95c8c2b671ffb93383d13dd842a696208 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _I386_MATH_EMU_H
-#define _I386_MATH_EMU_H
+#ifndef ASM_X86__MATH_EMU_H
+#define ASM_X86__MATH_EMU_H
 
 /* This structure matches the layout of the data saved to the stack
    following a device-not-present interrupt, part of it saved
@@ -28,4 +28,4 @@ struct info {
        long ___vm86_fs;
        long ___vm86_gs;
 };
-#endif
+#endif /* ASM_X86__MATH_EMU_H */
index daf1ccde77af32a855d21112693fd0b9e6d126e2..a995f33176cd026f60f21c18008811f9a5a996a4 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Machine dependent access functions for RTC registers.
  */
-#ifndef _ASM_MC146818RTC_H
-#define _ASM_MC146818RTC_H
+#ifndef ASM_X86__MC146818RTC_H
+#define ASM_X86__MC146818RTC_H
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -101,4 +101,4 @@ extern unsigned long mach_get_cmos_time(void);
 
 #define RTC_IRQ 8
 
-#endif /* _ASM_MC146818RTC_H */
+#endif /* ASM_X86__MC146818RTC_H */
index 09adf2eac4dce0517ea1b3b9c7c5173415fb6ff5..60d1ed287b1301c2907e910ab4c7c0e182df87bd 100644 (file)
@@ -1,8 +1,8 @@
 /* -*- mode: c; c-basic-offset: 8 -*- */
 
 /* Platform specific MCA defines */
-#ifndef _ASM_MCA_H
-#define _ASM_MCA_H
+#ifndef ASM_X86__MCA_H
+#define ASM_X86__MCA_H
 
 /* Maximal number of MCA slots - actually, some machines have less, but
  * they all have sufficient number of POS registers to cover 8.
@@ -40,4 +40,4 @@
  */
 #define MCA_NUMADAPTERS (MCA_MAX_SLOT_NR+3)
 
-#endif
+#endif /* ASM_X86__MCA_H */
index c3dca6edc6b1b82c3a252c4b005abc77106100d8..49f22be237d29c0e76e520d33b1fdb654f8a3d5d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef MCA_DMA_H
-#define MCA_DMA_H
+#ifndef ASM_X86__MCA_DMA_H
+#define ASM_X86__MCA_DMA_H
 
 #include <asm/io.h>
 #include <linux/ioport.h>
@@ -198,4 +198,4 @@ static inline void mca_set_dma_mode(unsigned int dmanr, unsigned int mode)
        outb(mode, MCA_DMA_REG_EXE);
 }
 
-#endif /* MCA_DMA_H */
+#endif /* ASM_X86__MCA_DMA_H */
index 94f1fd79e22a9512511b9660363290b535e7424e..6a580f24d4a4bb9049c7b2834bfeb6a3ce52246f 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_MCE_H
-#define _ASM_X86_MCE_H
+#ifndef ASM_X86__MCE_H
+#define ASM_X86__MCE_H
 
 #ifdef __x86_64__
 
@@ -126,4 +126,4 @@ extern void restart_mce(void);
 
 #endif /* __KERNEL__ */
 
-#endif
+#endif /* ASM_X86__MCE_H */
index c1682b542dafe2c02247e9d721fd69d335c874b7..b6b41aa1cbc837cefde500498e7e4d164865b4a5 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_MMAN_H
-#define _ASM_X86_MMAN_H
+#ifndef ASM_X86__MMAN_H
+#define ASM_X86__MMAN_H
 
 #include <asm-generic/mman.h>
 
@@ -16,4 +16,4 @@
 #define MCL_CURRENT    1               /* lock all current mappings */
 #define MCL_FUTURE     2               /* lock all future mappings */
 
-#endif /* _ASM_X86_MMAN_H */
+#endif /* ASM_X86__MMAN_H */
index 95beda07c6fa3e4fefbdd96bf2330c10cedbf674..8689f1e7bc01d6a8d629911c16000ea11e46a71d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_MMCONFIG_H
-#define _ASM_MMCONFIG_H
+#ifndef ASM_X86__MMCONFIG_H
+#define ASM_X86__MMCONFIG_H
 
 #ifdef CONFIG_PCI_MMCONFIG
 extern void __cpuinit fam10h_check_enable_mmcfg(void);
@@ -9,4 +9,4 @@ static inline void fam10h_check_enable_mmcfg(void) { }
 static inline void check_enable_amd_mmconf_dmi(void) { }
 #endif
 
-#endif
+#endif /* ASM_X86__MMCONFIG_H */
index 00e88679e11f780af5654ae54f2bfafc7e572369..a30d7a9c82972754ce35de9b166b9ccff6fec2be 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_MMU_H
-#define _ASM_X86_MMU_H
+#ifndef ASM_X86__MMU_H
+#define ASM_X86__MMU_H
 
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
@@ -28,4 +28,4 @@ static inline void leave_mm(int cpu)
 }
 #endif
 
-#endif /* _ASM_X86_MMU_H */
+#endif /* ASM_X86__MMU_H */
index fac57014e7c6a4a5dbb62a7ac9e884f400c57870..8ec940bfd07902b858a9c31c00292fa429132653 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_X86_MMU_CONTEXT_H
-#define __ASM_X86_MMU_CONTEXT_H
+#ifndef ASM_X86__MMU_CONTEXT_H
+#define ASM_X86__MMU_CONTEXT_H
 
 #include <asm/desc.h>
 #include <asm/atomic.h>
@@ -34,4 +34,4 @@ do {                                          \
 } while (0);
 
 
-#endif /* __ASM_X86_MMU_CONTEXT_H */
+#endif /* ASM_X86__MMU_CONTEXT_H */
index 824fc575c6d8370f03d747b6abedaadf21882903..cce6f6e4afd6dbc6c4c876fe505da7e828647384 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __I386_SCHED_H
-#define __I386_SCHED_H
+#ifndef ASM_X86__MMU_CONTEXT_32_H
+#define ASM_X86__MMU_CONTEXT_32_H
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
@@ -53,4 +53,4 @@ static inline void switch_mm(struct mm_struct *prev,
 #define deactivate_mm(tsk, mm)                 \
        asm("movl %0,%%gs": :"r" (0));
 
-#endif
+#endif /* ASM_X86__MMU_CONTEXT_32_H */
index c7000634ccae6900170be103a4b0fd99f571c55b..26758673c828b15068ea138a9527699ec7ae03d5 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __X86_64_MMU_CONTEXT_H
-#define __X86_64_MMU_CONTEXT_H
+#ifndef ASM_X86__MMU_CONTEXT_64_H
+#define ASM_X86__MMU_CONTEXT_64_H
 
 #include <asm/pda.h>
 
@@ -51,4 +51,4 @@ do {                                          \
        asm volatile("movl %0,%%fs"::"r"(0));   \
 } while (0)
 
-#endif
+#endif /* ASM_X86__MMU_CONTEXT_64_H */
index 940881218ff862ab13c349f107b2b5c6d050a5e5..2e7299bb3653639a00819fd72cea430c71d0b970 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_MMX_H
-#define _ASM_MMX_H
+#ifndef ASM_X86__MMX_H
+#define ASM_X86__MMX_H
 
 /*
  *     MMX 3Dnow! helper operations
@@ -11,4 +11,4 @@ extern void *_mmx_memcpy(void *to, const void *from, size_t size);
 extern void mmx_clear_page(void *page);
 extern void mmx_copy_page(void *to, void *from);
 
-#endif
+#endif /* ASM_X86__MMX_H */
index b2298a227567fa24f28bd04de70b0b80b70aaa93..b98590fdc9ea0388bdb2f7e4c66560f7cd86c4d8 100644 (file)
@@ -3,8 +3,8 @@
  *
  */
 
-#ifndef _ASM_MMZONE_H_
-#define _ASM_MMZONE_H_
+#ifndef ASM_X86__MMZONE_32_H
+#define ASM_X86__MMZONE_32_H
 
 #include <asm/smp.h>
 
@@ -125,4 +125,4 @@ static inline int pfn_valid(int pfn)
 })
 #endif /* CONFIG_NEED_MULTIPLE_NODES */
 
-#endif /* _ASM_MMZONE_H_ */
+#endif /* ASM_X86__MMZONE_32_H */
index 594bd0dc1d081db7865f80e5a33c4c8ab4f7a718..626b03a14875b20d54e2885fae78a602507f8577 100644 (file)
@@ -1,8 +1,8 @@
 /* K8 NUMA support */
 /* Copyright 2002,2003 by Andi Kleen, SuSE Labs */
 /* 2.5 Version loosely based on the NUMAQ Code by Pat Gaughen. */
-#ifndef _ASM_X86_64_MMZONE_H
-#define _ASM_X86_64_MMZONE_H 1
+#ifndef ASM_X86__MMZONE_64_H
+#define ASM_X86__MMZONE_64_H
 
 
 #ifdef CONFIG_NUMA
@@ -49,4 +49,4 @@ extern int early_pfn_to_nid(unsigned long pfn);
 #endif
 
 #endif
-#endif
+#endif /* ASM_X86__MMZONE_64_H */
index bfedb247871cfbc39ecb2823f428ac62f57eb9f4..48dc3e0c07d9a27b828ea614689a939e0baa581b 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_MODULE_H
-#define _ASM_MODULE_H
+#ifndef ASM_X86__MODULE_H
+#define ASM_X86__MODULE_H
 
 /* x86_32/64 are simple */
 struct mod_arch_specific {};
@@ -79,4 +79,4 @@ struct mod_arch_specific {};
 # define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE
 #endif
 
-#endif /* _ASM_MODULE_H */
+#endif /* ASM_X86__MODULE_H */
index b6995e567fcc64edff23e389bfad9ddeb5647508..118da365e371cf3415410fd902fd9ec85f537361 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _AM_X86_MPSPEC_H
-#define _AM_X86_MPSPEC_H
+#ifndef ASM_X86__MPSPEC_H
+#define ASM_X86__MPSPEC_H
 
 #include <linux/init.h>
 
@@ -141,4 +141,4 @@ static inline void physid_set_mask_of_physid(int physid, physid_mask_t *map)
 
 extern physid_mask_t phys_cpu_present_map;
 
-#endif
+#endif /* ASM_X86__MPSPEC_H */
index 38d1e73b49e41ebc1fdd8b07d697697b6b0fff0d..79166b04801231cf5d6526759113b071719a6226 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MPSPEC_DEF_H
-#define __ASM_MPSPEC_DEF_H
+#ifndef ASM_X86__MPSPEC_DEF_H
+#define ASM_X86__MPSPEC_DEF_H
 
 /*
  * Structure definitions for SMP machines following the
@@ -177,4 +177,4 @@ enum mp_bustype {
        MP_BUS_PCI,
        MP_BUS_MCA,
 };
-#endif
+#endif /* ASM_X86__MPSPEC_DEF_H */
index 7e4e9481f51cff18dda6f96cfcadb5c9d9535eb9..1b538c907a3de50b0fee5d87de36238560a9fce4 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_MSGBUF_H
-#define _ASM_X86_MSGBUF_H
+#ifndef ASM_X86__MSGBUF_H
+#define ASM_X86__MSGBUF_H
 
 /*
  * The msqid64_ds structure for i386 architecture.
@@ -36,4 +36,4 @@ struct msqid64_ds {
        unsigned long  __unused5;
 };
 
-#endif /* _ASM_X86_MSGBUF_H */
+#endif /* ASM_X86__MSGBUF_H */
index 296f29ce426d4e75a3c9451d1e16bb7d8aed3f71..ed91902468769a9efd074b20d529b47d046a25b6 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef ASM_MSIDEF_H
-#define ASM_MSIDEF_H
+#ifndef ASM_X86__MSIDEF_H
+#define ASM_X86__MSIDEF_H
 
 /*
  * Constants for Intel APIC based MSI messages.
@@ -48,4 +48,8 @@
 #define  MSI_ADDR_DEST_ID(dest)                (((dest) << MSI_ADDR_DEST_ID_SHIFT) & \
                                         MSI_ADDR_DEST_ID_MASK)
 
-#endif /* ASM_MSIDEF_H */
+#define MSI_ADDR_IR_EXT_INT            (1 << 4)
+#define MSI_ADDR_IR_SHV                        (1 << 3)
+#define MSI_ADDR_IR_INDEX1(index)      ((index & 0x8000) >> 13)
+#define MSI_ADDR_IR_INDEX2(index)      ((index & 0x7fff) << 5)
+#endif /* ASM_X86__MSIDEF_H */
index 44bce773012e80b11190b7400852f35a55683c98..3052f058ab063fb9cc0bf038986f4f34712320fc 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MSR_INDEX_H
-#define __ASM_MSR_INDEX_H
+#ifndef ASM_X86__MSR_INDEX_H
+#define ASM_X86__MSR_INDEX_H
 
 /* CPU model specific register (MSR) numbers */
 
 /* Geode defined MSRs */
 #define MSR_GEODE_BUSCONT_CONF0                0x00001900
 
-#endif /* __ASM_MSR_INDEX_H */
+#endif /* ASM_X86__MSR_INDEX_H */
index ca110ee73f074cf41550e7d7860eb412b7bb82ed..032992035bd9f73fabecce20f957b1dff051c717 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_X86_MSR_H_
-#define __ASM_X86_MSR_H_
+#ifndef ASM_X86__MSR_H
+#define ASM_X86__MSR_H
 
 #include <asm/msr-index.h>
 
@@ -220,4 +220,4 @@ static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 #endif /* __KERNEL__ */
 
 
-#endif
+#endif /* ASM_X86__MSR_H */
index a69a01a517292ffe4d902fd157e9adb201705a11..23a7f83da953e7dee776dd7abb001a0dd5ce1374 100644 (file)
@@ -20,8 +20,8 @@
     The postal address is:
       Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
 */
-#ifndef _ASM_X86_MTRR_H
-#define _ASM_X86_MTRR_H
+#ifndef ASM_X86__MTRR_H
+#define ASM_X86__MTRR_H
 
 #include <linux/ioctl.h>
 #include <linux/errno.h>
@@ -170,4 +170,4 @@ struct mtrr_gentry32 {
 
 #endif /* __KERNEL__ */
 
-#endif  /*  _ASM_X86_MTRR_H  */
+#endif /* ASM_X86__MTRR_H */
index 73e928ef5f03b6c6160788fa9f5df2efd89c78d6..25c16d8ba3c753995394e204258583a27eebbdf4 100644 (file)
@@ -6,8 +6,8 @@
  *
  *  Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
  */
-#ifndef _ASM_MUTEX_H
-#define _ASM_MUTEX_H
+#ifndef ASM_X86__MUTEX_32_H
+#define ASM_X86__MUTEX_32_H
 
 #include <asm/alternative.h>
 
@@ -122,4 +122,4 @@ static inline int __mutex_fastpath_trylock(atomic_t *count,
 #endif
 }
 
-#endif
+#endif /* ASM_X86__MUTEX_32_H */
index f3fae9becb387c0b758ed1a639be0591bdeeb129..918ba21ab9d9c5ec2c842e0479961694f379e2cd 100644 (file)
@@ -6,8 +6,8 @@
  *
  *  Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
  */
-#ifndef _ASM_MUTEX_H
-#define _ASM_MUTEX_H
+#ifndef ASM_X86__MUTEX_64_H
+#define ASM_X86__MUTEX_64_H
 
 /**
  * __mutex_fastpath_lock - decrement and call function if negative
@@ -97,4 +97,4 @@ static inline int __mutex_fastpath_trylock(atomic_t *count,
                return 0;
 }
 
-#endif
+#endif /* ASM_X86__MUTEX_64_H */
index 21f8d0202a828ee8f6d1bf14b444e2b340f6cb3d..f8b76f38390407bbe1b159e2c8b71175201fc5e1 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_NMI_H_
-#define _ASM_X86_NMI_H_
+#ifndef ASM_X86__NMI_H
+#define ASM_X86__NMI_H
 
 #include <linux/pm.h>
 #include <asm/irq.h>
@@ -81,4 +81,4 @@ void enable_lapic_nmi_watchdog(void);
 void stop_nmi(void);
 void restart_nmi(void);
 
-#endif
+#endif /* ASM_X86__NMI_H */
index ad0bedd10b89c8e1a66c6ea6668e1d12c6a7b35b..ae742721ae73e01cdfeb9ab4e1bc72310f5ec729 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_NOPS_H
-#define _ASM_NOPS_H 1
+#ifndef ASM_X86__NOPS_H
+#define ASM_X86__NOPS_H
 
 /* Define nops for use with alternative() */
 
 
 #define ASM_NOP_MAX 8
 
-#endif
+#endif /* ASM_X86__NOPS_H */
index 220d7b7707a02be8d82232d5395732a6f9a3efa2..44cb07855c5bcfd8ab4db962c3871316f5b9027c 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_32_NUMA_H
-#define _ASM_X86_32_NUMA_H 1
+#ifndef ASM_X86__NUMA_32_H
+#define ASM_X86__NUMA_32_H
 
 extern int pxm_to_nid(int pxm);
 extern void numa_remove_cpu(int cpu);
@@ -8,4 +8,4 @@ extern void numa_remove_cpu(int cpu);
 extern void set_highmem_pages_init(void);
 #endif
 
-#endif /* _ASM_X86_32_NUMA_H */
+#endif /* ASM_X86__NUMA_32_H */
index 3830094434a9ef75eb686bb2a84ef5c10daaaef7..15c990395b021b65c766b1321ea8801e4311f9f4 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X8664_NUMA_H
-#define _ASM_X8664_NUMA_H 1
+#ifndef ASM_X86__NUMA_64_H
+#define ASM_X86__NUMA_64_H
 
 #include <linux/nodemask.h>
 #include <asm/apicdef.h>
@@ -40,4 +40,4 @@ static inline void numa_add_cpu(int cpu, int node)    { }
 static inline void numa_remove_cpu(int cpu)            { }
 #endif
 
-#endif
+#endif /* ASM_X86__NUMA_64_H */
index 34b92d581fa326839f7c2568b82d9033472d44dd..124bf7d4b70a86d483fc25409e0a6105a3acca52 100644 (file)
@@ -23,8 +23,8 @@
  * Send feedback to <gone@us.ibm.com>
  */
 
-#ifndef NUMAQ_H
-#define NUMAQ_H
+#ifndef ASM_X86__NUMAQ_H
+#define ASM_X86__NUMAQ_H
 
 #ifdef CONFIG_X86_NUMAQ
 
@@ -165,5 +165,5 @@ static inline int get_memcfg_numaq(void)
        return 0;
 }
 #endif /* CONFIG_X86_NUMAQ */
-#endif /* NUMAQ_H */
+#endif /* ASM_X86__NUMAQ_H */
 
similarity index 97%
rename from include/asm-x86/mach-numaq/mach_apic.h
rename to include/asm-x86/numaq/apic.h
index d802465e026a4a5adb6834f90c0ea74caa672617..a8344ba6ea15064cd4898423c9b3fcd8183b25e1 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_APIC_H
-#define __ASM_MACH_APIC_H
+#ifndef __ASM_NUMAQ_APIC_H
+#define __ASM_NUMAQ_APIC_H
 
 #include <asm/io.h>
 #include <linux/mmzone.h>
@@ -135,4 +135,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
        return cpuid_apic >> index_msb;
 }
 
-#endif /* __ASM_MACH_APIC_H */
+#endif /* __ASM_NUMAQ_APIC_H */
similarity index 75%
rename from include/asm-x86/mach-numaq/mach_apicdef.h
rename to include/asm-x86/numaq/apicdef.h
index bf439d0690f54e0c74a7fdf70c9a1cbf900d691d..e012a46cc22a57baa0946e1b0230696aa7985b17 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_APICDEF_H
-#define __ASM_MACH_APICDEF_H
+#ifndef __ASM_NUMAQ_APICDEF_H
+#define __ASM_NUMAQ_APICDEF_H
 
 
 #define APIC_ID_MASK (0xF<<24)
similarity index 83%
rename from include/asm-x86/mach-numaq/mach_ipi.h
rename to include/asm-x86/numaq/ipi.h
index c6044488e9e6085a971c7a59640a56adefe22d7b..935588d286cf85c0ada9dbde94d83e74e081cf94 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_IPI_H
-#define __ASM_MACH_IPI_H
+#ifndef __ASM_NUMAQ_IPI_H
+#define __ASM_NUMAQ_IPI_H
 
 void send_IPI_mask_sequence(cpumask_t, int vector);
 
@@ -22,4 +22,4 @@ static inline void send_IPI_all(int vector)
        send_IPI_mask(cpu_online_map, vector);
 }
 
-#endif /* __ASM_MACH_IPI_H */
+#endif /* __ASM_NUMAQ_IPI_H */
similarity index 50%
rename from include/asm-x86/mach-numaq/mach_mpparse.h
rename to include/asm-x86/numaq/mpparse.h
index 626aef6b155f1498eee4ab3594eab6a4adeee00d..252292e077b6559be222c33a2f1b86458d618e39 100644 (file)
@@ -1,7 +1,7 @@
-#ifndef __ASM_MACH_MPPARSE_H
-#define __ASM_MACH_MPPARSE_H
+#ifndef __ASM_NUMAQ_MPPARSE_H
+#define __ASM_NUMAQ_MPPARSE_H
 
 extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
                                char *productid);
 
-#endif /* __ASM_MACH_MPPARSE_H */
+#endif /* __ASM_NUMAQ_MPPARSE_H */
similarity index 91%
rename from include/asm-x86/mach-numaq/mach_wakecpu.h
rename to include/asm-x86/numaq/wakecpu.h
index 00530041a991569f35e0da1fdd298bd96b8e6786..c577bda5b1c52c768047d1e664e0040356b57176 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_WAKECPU_H
-#define __ASM_MACH_WAKECPU_H
+#ifndef __ASM_NUMAQ_WAKECPU_H
+#define __ASM_NUMAQ_WAKECPU_H
 
 /* This file copes with machines that wakeup secondary CPUs by NMIs */
 
@@ -40,4 +40,4 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
 
 #define inquire_remote_apic(apicid) {}
 
-#endif /* __ASM_MACH_WAKECPU_H */
+#endif /* __ASM_NUMAQ_WAKECPU_H */
index 97d47133486f962687683793e19673b80da7af4b..d7328b1a05c1791dc9475a573a1574c65717ccd6 100644 (file)
@@ -1,7 +1,7 @@
 /* OLPC machine specific definitions */
 
-#ifndef ASM_OLPC_H_
-#define ASM_OLPC_H_
+#ifndef ASM_X86__OLPC_H
+#define ASM_X86__OLPC_H
 
 #include <asm/geode.h>
 
@@ -129,4 +129,4 @@ extern int olpc_ec_mask_unset(uint8_t bits);
 #define OLPC_GPIO_LID          geode_gpio(26)
 #define OLPC_GPIO_ECSCI                geode_gpio(27)
 
-#endif
+#endif /* ASM_X86__OLPC_H */
index 49982110e4d94e4025896a6c05d7fddecca382ae..79544e6ffb8b8b06060ddb93988972b618e3ef02 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_PAGE_H
-#define _ASM_X86_PAGE_H
+#ifndef ASM_X86__PAGE_H
+#define ASM_X86__PAGE_H
 
 #include <linux/const.h>
 
@@ -199,4 +199,4 @@ static inline pteval_t native_pte_flags(pte_t pte)
 #define __HAVE_ARCH_GATE_AREA 1
 
 #endif /* __KERNEL__ */
-#endif /* _ASM_X86_PAGE_H */
+#endif /* ASM_X86__PAGE_H */
index c9dd069d4ef0834fcb145d756e17c350f8619f70..f32062a821c532d18745347458ec133e9bc803c9 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_PAGE_32_H
-#define _ASM_X86_PAGE_32_H
+#ifndef ASM_X86__PAGE_32_H
+#define ASM_X86__PAGE_32_H
 
 /*
  * This handles the memory map.
@@ -127,4 +127,4 @@ static inline void copy_page(void *to, void *from)
 #endif /* CONFIG_X86_3DNOW */
 #endif /* !__ASSEMBLY__ */
 
-#endif /* _ASM_X86_PAGE_32_H */
+#endif /* ASM_X86__PAGE_32_H */
index e5a754e97f25cff12496ad928b29cbe2b39d0f00..5e64acfed0a4882b1bf392e0541b03df8d53734f 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _X86_64_PAGE_H
-#define _X86_64_PAGE_H
+#ifndef ASM_X86__PAGE_64_H
+#define ASM_X86__PAGE_64_H
 
 #define PAGETABLE_LEVELS       4
 
@@ -103,4 +103,4 @@ extern void init_extra_mapping_wb(unsigned long phys, unsigned long size);
 #endif
 
 
-#endif /* _X86_64_PAGE_H */
+#endif /* ASM_X86__PAGE_64_H */
index 6f0d0422f4ca0ffdcb07df874789dc565f3ac82f..0009cfb11a5f53bbba0c697a6695cb6bddfefa7d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_PARAM_H
-#define _ASM_X86_PARAM_H
+#ifndef ASM_X86__PARAM_H
+#define ASM_X86__PARAM_H
 
 #ifdef __KERNEL__
 # define HZ            CONFIG_HZ       /* Internal kernel timer frequency */
@@ -19,4 +19,4 @@
 
 #define MAXHOSTNAMELEN 64      /* max length of hostname */
 
-#endif /* _ASM_X86_PARAM_H */
+#endif /* ASM_X86__PARAM_H */
index fbbde93f12d6d5ad0aaca4fb1e6db0860cb5a351..ff9a7e4bc3f62c69222bbb34117753fa5d6bd8ca 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_PARAVIRT_H
-#define __ASM_PARAVIRT_H
+#ifndef ASM_X86__PARAVIRT_H
+#define ASM_X86__PARAVIRT_H
 /* Various instructions on x86 need to be replaced for
  * para-virtualization: those hooks are defined here. */
 
@@ -200,12 +200,6 @@ struct pv_irq_ops {
 
 struct pv_apic_ops {
 #ifdef CONFIG_X86_LOCAL_APIC
-       /*
-        * Direct APIC operations, principally for VMI.  Ideally
-        * these shouldn't be in this interface.
-        */
-       void (*apic_write)(unsigned long reg, u32 v);
-       u32 (*apic_read)(unsigned long reg);
        void (*setup_boot_clock)(void);
        void (*setup_secondary_clock)(void);
 
@@ -898,19 +892,6 @@ static inline void slow_down_io(void)
 }
 
 #ifdef CONFIG_X86_LOCAL_APIC
-/*
- * Basic functions accessing APICs.
- */
-static inline void apic_write(unsigned long reg, u32 v)
-{
-       PVOP_VCALL2(pv_apic_ops.apic_write, reg, v);
-}
-
-static inline u32 apic_read(unsigned long reg)
-{
-       return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg);
-}
-
 static inline void setup_boot_clock(void)
 {
        PVOP_VCALL0(pv_apic_ops.setup_boot_clock);
@@ -1634,4 +1615,4 @@ static inline unsigned long __raw_local_irq_save(void)
 
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_PARAVIRT */
-#endif /* __ASM_PARAVIRT_H */
+#endif /* ASM_X86__PARAVIRT_H */
index 3c4ffeb467e9886ad62b1a4c6bf60686fcb219a3..2e3dda4dc3d9b9f4bc243ca5a5b82b15be18263c 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_PARPORT_H
-#define _ASM_X86_PARPORT_H
+#ifndef ASM_X86__PARPORT_H
+#define ASM_X86__PARPORT_H
 
 static int __devinit parport_pc_find_isa_ports(int autoirq, int autodma);
 static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma)
@@ -7,4 +7,4 @@ static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma)
        return parport_pc_find_isa_ports(autoirq, autodma);
 }
 
-#endif /* _ASM_X86_PARPORT_H */
+#endif /* ASM_X86__PARPORT_H */
index 7edc473072179c48defd9043a2ec5be0202dbbcf..482c3e3f9879b23f086274fbd7dc453c3701ed69 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_PAT_H
-#define _ASM_PAT_H
+#ifndef ASM_X86__PAT_H
+#define ASM_X86__PAT_H
 
 #include <linux/types.h>
 
@@ -19,4 +19,4 @@ extern int free_memtype(u64 start, u64 end);
 
 extern void pat_disable(char *reason);
 
-#endif
+#endif /* ASM_X86__PAT_H */
index 80c775d9fe205810257fb8dc0013b997b5d61969..da42be07b6907bbfcf6eecabeaa65a2546cb40a1 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef ASM_PCI_DIRECT_H
-#define ASM_PCI_DIRECT_H 1
+#ifndef ASM_X86__PCI_DIRECT_H
+#define ASM_X86__PCI_DIRECT_H
 
 #include <linux/types.h>
 
@@ -18,4 +18,4 @@ extern int early_pci_allowed(void);
 extern unsigned int pci_early_dump_regs;
 extern void early_dump_pci_device(u8 bus, u8 slot, u8 func);
 extern void early_dump_pci_devices(void);
-#endif
+#endif /* ASM_X86__PCI_DIRECT_H */
index 2db14cf17db8f9faeae76133445f144023d58ff6..60258319299183fa10ba7127f8af81a4e45f4f4e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __x86_PCI_H
-#define __x86_PCI_H
+#ifndef ASM_X86__PCI_H
+#define ASM_X86__PCI_H
 
 #include <linux/mm.h> /* for struct page */
 #include <linux/types.h>
@@ -111,4 +111,4 @@ static inline cpumask_t __pcibus_to_cpumask(struct pci_bus *bus)
 }
 #endif
 
-#endif
+#endif /* ASM_X86__PCI_H */
index a50d468512857e2dd9cbdecf3b76fd986e15b1d4..3f2288207c0cd0e664cce2037d7c25e4a1bf1166 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __i386_PCI_H
-#define __i386_PCI_H
+#ifndef ASM_X86__PCI_32_H
+#define ASM_X86__PCI_32_H
 
 
 #ifdef __KERNEL__
@@ -31,4 +31,4 @@ struct pci_dev;
 #endif /* __KERNEL__ */
 
 
-#endif /* __i386_PCI_H */
+#endif /* ASM_X86__PCI_32_H */
index f330234ffa5c568888aeabf92c1e7a49d91335dc..f72e12d5770ef275aff119c8c136a70b75ed047a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __x8664_PCI_H
-#define __x8664_PCI_H
+#ifndef ASM_X86__PCI_64_H
+#define ASM_X86__PCI_64_H
 
 #ifdef __KERNEL__
 
@@ -63,4 +63,4 @@ extern void pci_iommu_alloc(void);
 
 #endif /* __KERNEL__ */
 
-#endif /* __x8664_PCI_H */
+#endif /* ASM_X86__PCI_64_H */
index b34e9a7cc80b3002dc9e331f224298d8754482f1..80860afffbdbbede4092bb18a6946e5b0a2831f9 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef X86_64_PDA_H
-#define X86_64_PDA_H
+#ifndef ASM_X86__PDA_H
+#define ASM_X86__PDA_H
 
 #ifndef __ASSEMBLY__
 #include <linux/stddef.h>
@@ -134,4 +134,4 @@ do {                                                                        \
 
 #define PDA_STACKOFFSET (5*8)
 
-#endif
+#endif /* ASM_X86__PDA_H */
index 4e91ee1e37aa170140e92814a08232fef4e6dfd4..0afc8324807eb0248047ab5261fc36b966b55db2 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_PERCPU_H_
-#define _ASM_X86_PERCPU_H_
+#ifndef ASM_X86__PERCPU_H
+#define ASM_X86__PERCPU_H
 
 #ifdef CONFIG_X86_64
 #include <linux/compiler.h>
@@ -215,4 +215,4 @@ do {                                                        \
 
 #endif /* !CONFIG_SMP */
 
-#endif /* _ASM_X86_PERCPU_H_ */
+#endif /* ASM_X86__PERCPU_H */
index d63ea431cb3bbc974bec3fa3b22e5afff0194c17..3cd23adedae851d13da954b3cb8574390102931a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_PGALLOC_H
-#define _ASM_X86_PGALLOC_H
+#ifndef ASM_X86__PGALLOC_H
+#define ASM_X86__PGALLOC_H
 
 #include <linux/threads.h>
 #include <linux/mm.h>          /* for struct page */
@@ -111,4 +111,4 @@ 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 */
+#endif /* ASM_X86__PGALLOC_H */
index 0f71c9f13da4a406e8f6e6e7d3225fe30e72c983..7ec48f4e53472a865eee5d9fb4c1b018bd3fcd8a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _I386_PGTABLE_2LEVEL_DEFS_H
-#define _I386_PGTABLE_2LEVEL_DEFS_H
+#ifndef ASM_X86__PGTABLE_2LEVEL_DEFS_H
+#define ASM_X86__PGTABLE_2LEVEL_DEFS_H
 
 #define SHARED_KERNEL_PMD      0
 
@@ -17,4 +17,4 @@
 
 #define PTRS_PER_PTE   1024
 
-#endif /* _I386_PGTABLE_2LEVEL_DEFS_H */
+#endif /* ASM_X86__PGTABLE_2LEVEL_DEFS_H */
index 46bc52c0eae18ce519f1fe073edbed48ab846dc8..60440b1916266c4343c60dd7f7086cc9b7bbfb45 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _I386_PGTABLE_2LEVEL_H
-#define _I386_PGTABLE_2LEVEL_H
+#ifndef ASM_X86__PGTABLE_2LEVEL_H
+#define ASM_X86__PGTABLE_2LEVEL_H
 
 #define pte_ERROR(e) \
        printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low)
@@ -78,4 +78,4 @@ static inline pte_t native_ptep_get_and_clear(pte_t *xp)
 #define __pte_to_swp_entry(pte)                ((swp_entry_t) { (pte).pte_low })
 #define __swp_entry_to_pte(x)          ((pte_t) { .pte = (x).val })
 
-#endif /* _I386_PGTABLE_2LEVEL_H */
+#endif /* ASM_X86__PGTABLE_2LEVEL_H */
index 448ac95163145c4ded12b5d3a8db3c911d617bd3..c05fe6ff37202ddd51c596b9c27e1b609f84fb3a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _I386_PGTABLE_3LEVEL_DEFS_H
-#define _I386_PGTABLE_3LEVEL_DEFS_H
+#ifndef ASM_X86__PGTABLE_3LEVEL_DEFS_H
+#define ASM_X86__PGTABLE_3LEVEL_DEFS_H
 
 #ifdef CONFIG_PARAVIRT
 #define SHARED_KERNEL_PMD      (pv_info.shared_kernel_pmd)
@@ -25,4 +25,4 @@
  */
 #define PTRS_PER_PTE   512
 
-#endif /* _I386_PGTABLE_3LEVEL_DEFS_H */
+#endif /* ASM_X86__PGTABLE_3LEVEL_DEFS_H */
index 105057f34032f0a23610ea5822e32cf12d51b4f7..e713bd5f39a684b4c88ef81aa7c6f9a468db9c88 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _I386_PGTABLE_3LEVEL_H
-#define _I386_PGTABLE_3LEVEL_H
+#ifndef ASM_X86__PGTABLE_3LEVEL_H
+#define ASM_X86__PGTABLE_3LEVEL_H
 
 /*
  * Intel Physical Address Extension (PAE) Mode - three-level page
@@ -179,4 +179,4 @@ static inline unsigned long pte_pfn(pte_t pte)
 #define __pte_to_swp_entry(pte)                ((swp_entry_t){ (pte).pte_high })
 #define __swp_entry_to_pte(x)          ((pte_t){ { .pte_high = (x).val } })
 
-#endif /* _I386_PGTABLE_3LEVEL_H */
+#endif /* ASM_X86__PGTABLE_3LEVEL_H */
index 5359ec54c4b96d09d5dad257bd59d829c3d04027..57d919a2d79d94c944d91e75bf08cd442de01e46 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_PGTABLE_H
-#define _ASM_X86_PGTABLE_H
+#ifndef ASM_X86__PGTABLE_H
+#define ASM_X86__PGTABLE_H
 
 #define FIRST_USER_ADDRESS     0
 
@@ -523,4 +523,4 @@ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
 #include <asm-generic/pgtable.h>
 #endif /* __ASSEMBLY__ */
 
-#endif /* _ASM_X86_PGTABLE_H */
+#endif /* ASM_X86__PGTABLE_H */
index 64c75923814668c09f63e3d2aa5fea4d25e9f448..45c8235400fedc0db4e138b48b8cf60a92c73617 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _I386_PGTABLE_H
-#define _I386_PGTABLE_H
+#ifndef ASM_X86__PGTABLE_32_H
+#define ASM_X86__PGTABLE_32_H
 
 
 /*
@@ -187,4 +187,4 @@ do {                                                \
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)        \
        remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#endif /* _I386_PGTABLE_H */
+#endif /* ASM_X86__PGTABLE_32_H */
index ac5fff4cc58aaf364eb41d5027f8e851aceef915..609c24975c663d85b168f36748443b15df1b260d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _X86_64_PGTABLE_H
-#define _X86_64_PGTABLE_H
+#ifndef ASM_X86__PGTABLE_64_H
+#define ASM_X86__PGTABLE_64_H
 
 #include <linux/const.h>
 #ifndef __ASSEMBLY__
@@ -284,4 +284,4 @@ extern void cleanup_highmap(void);
 #define __HAVE_ARCH_PTE_SAME
 #endif /* !__ASSEMBLY__ */
 
-#endif /* _X86_64_PGTABLE_H */
+#endif /* ASM_X86__PGTABLE_64_H */
index b031efda37ec047417dc22b6c7b61ffd7c095b19..70cf2bb059393532401e0eb4bc49528b869c5f84 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ARCH_I386_POSIX_TYPES_H
-#define __ARCH_I386_POSIX_TYPES_H
+#ifndef ASM_X86__POSIX_TYPES_32_H
+#define ASM_X86__POSIX_TYPES_32_H
 
 /*
  * This file is generally used by user-level software, so you need to
@@ -82,4 +82,4 @@ do {                                                          \
 
 #endif /* defined(__KERNEL__) */
 
-#endif
+#endif /* ASM_X86__POSIX_TYPES_32_H */
index d6624c95854af6b27db8fe2d371e3536f2862a9d..388b4e7f4a440425173adfd5f6da9bd25ead676c 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_64_POSIX_TYPES_H
-#define _ASM_X86_64_POSIX_TYPES_H
+#ifndef ASM_X86__POSIX_TYPES_64_H
+#define ASM_X86__POSIX_TYPES_64_H
 
 /*
  * This file is generally used by user-level software, so you need to
@@ -116,4 +116,4 @@ static inline void __FD_ZERO(__kernel_fd_set *p)
 
 #endif /* defined(__KERNEL__) */
 
-#endif
+#endif /* ASM_X86__POSIX_TYPES_64_H */
index 52952adef1ca8fbd4d04b14eae63f2f6315479ac..e7ae34eb4103357ac3a8b73352df7fce8caed93d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef X86_64_PRCTL_H
-#define X86_64_PRCTL_H 1
+#ifndef ASM_X86__PRCTL_H
+#define ASM_X86__PRCTL_H
 
 #define ARCH_SET_GS 0x1001
 #define ARCH_SET_FS 0x1002
@@ -7,4 +7,4 @@
 #define ARCH_GET_GS 0x1004
 
 
-#endif
+#endif /* ASM_X86__PRCTL_H */
index eff2ecd7fff067caf89bc48cd81bebe111a43363..5dd79774f693c176d66e8e2d5ef7639d85569c25 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_I386_PROCESSOR_FLAGS_H
-#define __ASM_I386_PROCESSOR_FLAGS_H
+#ifndef ASM_X86__PROCESSOR_FLAGS_H
+#define ASM_X86__PROCESSOR_FLAGS_H
 /* Various flags defined: can be included from assembler. */
 
 /*
@@ -96,4 +96,4 @@
 #endif
 #endif
 
-#endif /* __ASM_I386_PROCESSOR_FLAGS_H */
+#endif /* ASM_X86__PROCESSOR_FLAGS_H */
index 3c5dc562b0f62afb5e17b07baba8c9b8d1595b89..6d5648945ebf86fff45e85b5fe3cf64c6a65697e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_X86_PROCESSOR_H
-#define __ASM_X86_PROCESSOR_H
+#ifndef ASM_X86__PROCESSOR_H
+#define ASM_X86__PROCESSOR_H
 
 #include <asm/processor-flags.h>
 
@@ -924,4 +924,4 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
 extern int get_tsc_mode(unsigned long adr);
 extern int set_tsc_mode(unsigned int val);
 
-#endif
+#endif /* ASM_X86__PROCESSOR_H */
index 3dd458c385c0532b59ce3aac67386ad215665dc9..6e89e8b4de0ec1c9f20f30ee2736116666a01d0e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X8664_PROTO_H
-#define _ASM_X8664_PROTO_H 1
+#ifndef ASM_X86__PROTO_H
+#define ASM_X86__PROTO_H
 
 #include <asm/ldt.h>
 
@@ -29,4 +29,4 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
 #define round_up(x, y) (((x) + (y) - 1) & ~((y) - 1))
 #define round_down(x, y) ((x) & ~((y) - 1))
 
-#endif
+#endif /* ASM_X86__PROTO_H */
index 72e7b9db29bba0e2cb736d86281ab4f7c24cdd1d..d0cf3344a586ccedc403472fa179039049b737c4 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_PTRACE_ABI_H
-#define _ASM_X86_PTRACE_ABI_H
+#ifndef ASM_X86__PTRACE_ABI_H
+#define ASM_X86__PTRACE_ABI_H
 
 #ifdef __i386__
 
@@ -140,4 +140,4 @@ struct ptrace_bts_config {
    Returns number of BTS records drained.
 */
 
-#endif
+#endif /* ASM_X86__PTRACE_ABI_H */
index 48c1d5a890de0492747dce053a38b519a5da19e7..66ff7bd4737990175ee1db3889b9734a0d486b97 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_PTRACE_H
-#define _ASM_X86_PTRACE_H
+#ifndef ASM_X86__PTRACE_H
+#define ASM_X86__PTRACE_H
 
 #include <linux/compiler.h>    /* For __user */
 #include <asm/ptrace-abi.h>
@@ -242,4 +242,4 @@ extern int do_set_thread_area(struct task_struct *p, int idx,
 
 #endif /* !__ASSEMBLY__ */
 
-#endif
+#endif /* ASM_X86__PTRACE_H */
index 6857f840b2436500a0483c37bb494cf2e388d939..edb3b4ecfc81687e46ff5aa8f24fb1a696349932 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_PVCLOCK_ABI_H_
-#define _ASM_X86_PVCLOCK_ABI_H_
+#ifndef ASM_X86__PVCLOCK_ABI_H
+#define ASM_X86__PVCLOCK_ABI_H
 #ifndef __ASSEMBLY__
 
 /*
@@ -39,4 +39,4 @@ struct pvclock_wall_clock {
 } __attribute__((__packed__));
 
 #endif /* __ASSEMBLY__ */
-#endif /* _ASM_X86_PVCLOCK_ABI_H_ */
+#endif /* ASM_X86__PVCLOCK_ABI_H */
index 85b1bba8e0a34a2ac4121e1fe04324f02efdb603..1a38f68348007a64dfabf488dd623bef2a463f42 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_PVCLOCK_H_
-#define _ASM_X86_PVCLOCK_H_
+#ifndef ASM_X86__PVCLOCK_H
+#define ASM_X86__PVCLOCK_H
 
 #include <linux/clocksource.h>
 #include <asm/pvclock-abi.h>
@@ -10,4 +10,4 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
                            struct pvclock_vcpu_time_info *vcpu,
                            struct timespec *ts);
 
-#endif /* _ASM_X86_PVCLOCK_H_ */
+#endif /* ASM_X86__PVCLOCK_H */
index 206f355786dc5651b11777305974b281bb7a4e9f..1c2f0ce9e31e44b2c7cd8ab8a30e708f95db44c6 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_REBOOT_H
-#define _ASM_REBOOT_H
+#ifndef ASM_X86__REBOOT_H
+#define ASM_X86__REBOOT_H
 
 struct pt_regs;
 
@@ -18,4 +18,4 @@ void native_machine_crash_shutdown(struct pt_regs *regs);
 void native_machine_shutdown(void);
 void machine_real_restart(const unsigned char *code, int length);
 
-#endif /* _ASM_REBOOT_H */
+#endif /* ASM_X86__REBOOT_H */
index 0cb7d87c2b6847019032523fded1e6b4792bfdd4..2c2987d975706e891bbb5e58021b3158eacaac4a 100644 (file)
@@ -1,6 +1,6 @@
-#ifndef _LINUX_REBOOT_FIXUPS_H
-#define _LINUX_REBOOT_FIXUPS_H
+#ifndef ASM_X86__REBOOT_FIXUPS_H
+#define ASM_X86__REBOOT_FIXUPS_H
 
 extern void mach_reboot_fixups(void);
 
-#endif /* _LINUX_REBOOT_FIXUPS_H */
+#endif /* ASM_X86__REBOOT_FIXUPS_H */
index adec887dd7cd5f07c1148f8c233e033e05160e40..d6822e099c57a1b519df6dfd239c6465f200a585 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_REQUIRED_FEATURES_H
-#define _ASM_REQUIRED_FEATURES_H 1
+#ifndef ASM_X86__REQUIRED_FEATURES_H
+#define ASM_X86__REQUIRED_FEATURES_H
 
 /* Define minimum CPUID feature set for kernel These bits are checked
    really early to actually display a visible error message before the
@@ -73,4 +73,4 @@
 #define REQUIRED_MASK6 0
 #define REQUIRED_MASK7 0
 
-#endif
+#endif /* ASM_X86__REQUIRED_FEATURES_H */
index 8d9f0b41ee86ca40f7f9b19d02f43c76348e1069..519a8ecbfc95c46ba36bd2e118ec365034f9980d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_RESUME_TRACE_H
-#define _ASM_X86_RESUME_TRACE_H
+#ifndef ASM_X86__RESUME_TRACE_H
+#define ASM_X86__RESUME_TRACE_H
 
 #include <asm/asm.h>
 
@@ -18,4 +18,4 @@ do {                                                          \
        }                                                       \
 } while (0)
 
-#endif
+#endif /* ASM_X86__RESUME_TRACE_H */
index c9448bd8968f3696f800d240078e3b0510e101b7..5e1256bdee83b791499000cb873b0135437e826f 100644 (file)
@@ -5,8 +5,8 @@
  * Author: Laurent Vivier <Laurent.Vivier@bull.net>
  */
 
-#ifndef __ASM_RIO_H
-#define __ASM_RIO_H
+#ifndef ASM_X86__RIO_H
+#define ASM_X86__RIO_H
 
 #define RIO_TABLE_VERSION      3
 
@@ -60,4 +60,4 @@ enum {
        ALT_CALGARY     = 5,    /* Second Planar Calgary      */
 };
 
-#endif /* __ASM_RIO_H */
+#endif /* ASM_X86__RIO_H */
index 6a8c0d6451080658c6b2bee54fad409b11d47a9a..48a3109e1a7d83e1101c13864c444dcad3741fad 100644 (file)
@@ -1,8 +1,8 @@
-#ifndef _ASM_X86_RWLOCK_H
-#define _ASM_X86_RWLOCK_H
+#ifndef ASM_X86__RWLOCK_H
+#define ASM_X86__RWLOCK_H
 
 #define RW_LOCK_BIAS            0x01000000
 
 /* Actual code is in asm/spinlock.h or in arch/x86/lib/rwlock.S */
 
-#endif /* _ASM_X86_RWLOCK_H */
+#endif /* ASM_X86__RWLOCK_H */
index 750f2a3542b3931044e77835dceac28457bbece8..3ff3015b71a8367f738cb8c1974c09665b569ed3 100644 (file)
@@ -29,8 +29,8 @@
  * front, then they'll all be woken up, but no other readers will be.
  */
 
-#ifndef _I386_RWSEM_H
-#define _I386_RWSEM_H
+#ifndef ASM_X86__RWSEM_H
+#define ASM_X86__RWSEM_H
 
 #ifndef _LINUX_RWSEM_H
 #error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
@@ -262,4 +262,4 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem)
 }
 
 #endif /* __KERNEL__ */
-#endif /* _I386_RWSEM_H */
+#endif /* ASM_X86__RWSEM_H */
index c0432061f81a0f0609e8b115e3c23e4ff6cdcbb4..ee48f880005d13e8244c56bf6a59cb68845fdd2e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SCATTERLIST_H
-#define _ASM_X86_SCATTERLIST_H
+#ifndef ASM_X86__SCATTERLIST_H
+#define ASM_X86__SCATTERLIST_H
 
 #include <asm/types.h>
 
@@ -30,4 +30,4 @@ struct scatterlist {
 # define sg_dma_len(sg)                ((sg)->dma_length)
 #endif
 
-#endif
+#endif /* ASM_X86__SCATTERLIST_H */
index 36e71c5f306f0d29d23e7856af34cf46bfc7238c..cf9ab2dbcef1f07c0e3f864579d8f75c721a6005 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_SECCOMP_H
-#define _ASM_SECCOMP_H
+#ifndef ASM_X86__SECCOMP_32_H
+#define ASM_X86__SECCOMP_32_H
 
 #include <linux/thread_info.h>
 
@@ -14,4 +14,4 @@
 #define __NR_seccomp_exit __NR_exit
 #define __NR_seccomp_sigreturn __NR_sigreturn
 
-#endif /* _ASM_SECCOMP_H */
+#endif /* ASM_X86__SECCOMP_32_H */
index 76cfe69aa63c655d969fd80994193697637326bc..03274cea751f78e460afdd6fa66bb4c1937cb3c1 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_SECCOMP_H
-#define _ASM_SECCOMP_H
+#ifndef ASM_X86__SECCOMP_64_H
+#define ASM_X86__SECCOMP_64_H
 
 #include <linux/thread_info.h>
 
@@ -22,4 +22,4 @@
 #define __NR_seccomp_exit_32 __NR_ia32_exit
 #define __NR_seccomp_sigreturn_32 __NR_ia32_sigreturn
 
-#endif /* _ASM_SECCOMP_H */
+#endif /* ASM_X86__SECCOMP_64_H */
index 646452ea9ea3ede3d7847f5be78c8ca5a0feee48..ea5f0a8686f7539e32e92f801574454c9b3a6846 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SEGMENT_H_
-#define _ASM_X86_SEGMENT_H_
+#ifndef ASM_X86__SEGMENT_H
+#define ASM_X86__SEGMENT_H
 
 /* Constructor for a conventional segment GDT (or LDT) entry */
 /* This is a macro so it can be used in initializers */
@@ -212,4 +212,4 @@ extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][10];
 #endif
 #endif
 
-#endif
+#endif /* ASM_X86__SEGMENT_H */
index ee50c801f7b7eda1d4ea2aeea1f99cfaf1b03ccd..81f06b7e5a3f2685a88a1b7103253c3a69e34c79 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SEMBUF_H
-#define _ASM_X86_SEMBUF_H
+#ifndef ASM_X86__SEMBUF_H
+#define ASM_X86__SEMBUF_H
 
 /*
  * The semid64_ds structure for x86 architecture.
@@ -21,4 +21,4 @@ struct semid64_ds {
        unsigned long   __unused4;
 };
 
-#endif /* _ASM_X86_SEMBUF_H */
+#endif /* ASM_X86__SEMBUF_H */
index 628c801535ea912c00a57654310a832acca2e67f..303660b671e5cf6d07d02201578225cc0dfcb3ee 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SERIAL_H
-#define _ASM_X86_SERIAL_H
+#ifndef ASM_X86__SERIAL_H
+#define ASM_X86__SERIAL_H
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
@@ -26,4 +26,4 @@
        { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },      /* ttyS2 */     \
        { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },     /* ttyS3 */
 
-#endif /* _ASM_X86_SERIAL_H */
+#endif /* ASM_X86__SERIAL_H */
index 946f8f20e91c445498a267d0408f356e8ca24951..11b6cc14b289686f3eff7ae2d908540fc866b747 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SETUP_H
-#define _ASM_X86_SETUP_H
+#ifndef ASM_X86__SETUP_H
+#define ASM_X86__SETUP_H
 
 #define COMMAND_LINE_SIZE 2048
 
@@ -38,6 +38,7 @@ struct x86_quirks {
        void (*mpc_oem_pci_bus)(struct mpc_config_bus *m);
        void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable,
                                     unsigned short oemsize);
+       int (*setup_ioapic_ids)(void);
 };
 
 extern struct x86_quirks *x86_quirks;
@@ -101,4 +102,4 @@ void __init x86_64_start_reservations(char *real_mode_data);
 #endif /* __ASSEMBLY__ */
 #endif  /*  __KERNEL__  */
 
-#endif /* _ASM_X86_SETUP_H */
+#endif /* ASM_X86__SETUP_H */
index b51413b749711f133882d9e21c432d4c28a68463..f51aec2298e9998f919d87bc734da9d994d82860 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SHMBUF_H
-#define _ASM_X86_SHMBUF_H
+#ifndef ASM_X86__SHMBUF_H
+#define ASM_X86__SHMBUF_H
 
 /*
  * The shmid64_ds structure for x86 architecture.
@@ -48,4 +48,4 @@ struct shminfo64 {
        unsigned long   __unused4;
 };
 
-#endif /* _ASM_X86_SHMBUF_H */
+#endif /* ASM_X86__SHMBUF_H */
index 0880cf0917b9ac3c1332d00700b96ebd3e7d012c..a83a1fd96a0e5a155b432d9fda755a7604882482 100644 (file)
@@ -1,6 +1,6 @@
-#ifndef _ASM_X86_SHMPARAM_H
-#define _ASM_X86_SHMPARAM_H
+#ifndef ASM_X86__SHMPARAM_H
+#define ASM_X86__SHMPARAM_H
 
 #define SHMLBA PAGE_SIZE        /* attach addr a multiple of this */
 
-#endif /* _ASM_X86_SHMPARAM_H */
+#endif /* ASM_X86__SHMPARAM_H */
index 2f9c884d2c0f3950f8a8179a6bd440fee0b228eb..24879c85b2914ec91821f0a67650706d45f3b3c2 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SIGCONTEXT_H
-#define _ASM_X86_SIGCONTEXT_H
+#ifndef ASM_X86__SIGCONTEXT_H
+#define ASM_X86__SIGCONTEXT_H
 
 #include <linux/compiler.h>
 #include <asm/types.h>
@@ -202,4 +202,4 @@ struct sigcontext {
 
 #endif /* !__i386__ */
 
-#endif
+#endif /* ASM_X86__SIGCONTEXT_H */
index 57a9686fb4917a74d0ca9f6f6f18ffd3b5bdb665..4e2ec732dd0130ac278408db300a65c2b095dd94 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _SIGCONTEXT32_H
-#define _SIGCONTEXT32_H 1
+#ifndef ASM_X86__SIGCONTEXT32_H
+#define ASM_X86__SIGCONTEXT32_H
 
 /* signal context for 32bit programs. */
 
@@ -68,4 +68,4 @@ struct sigcontext_ia32 {
        unsigned int cr2;
 };
 
-#endif
+#endif /* ASM_X86__SIGCONTEXT32_H */
index a477bea0c2a12d6dd81e356470d467fb77c7ee4e..808bdfb2958c600628df8fbc52317169033e6492 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SIGINFO_H
-#define _ASM_X86_SIGINFO_H
+#ifndef ASM_X86__SIGINFO_H
+#define ASM_X86__SIGINFO_H
 
 #ifdef __x86_64__
 # define __ARCH_SI_PREAMBLE_SIZE       (4 * sizeof(int))
@@ -7,4 +7,4 @@
 
 #include <asm-generic/siginfo.h>
 
-#endif
+#endif /* ASM_X86__SIGINFO_H */
index 5e4a1b0d8dc3bc5aacee6641605bfea4885ec73b..65acc82d267a6f3b75a42f856ae9b0ec007cf70a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SIGNAL_H
-#define _ASM_X86_SIGNAL_H
+#ifndef ASM_X86__SIGNAL_H
+#define ASM_X86__SIGNAL_H
 
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
@@ -259,4 +259,4 @@ struct pt_regs;
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 
-#endif
+#endif /* ASM_X86__SIGNAL_H */
index 3a1480648f65b068b61ba30b7398f2b8e3c0e50b..29324c103341d4f2653c36d561f665eca7e5094b 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SMP_H_
-#define _ASM_X86_SMP_H_
+#ifndef ASM_X86__SMP_H
+#define ASM_X86__SMP_H
 #ifndef __ASSEMBLY__
 #include <linux/cpumask.h>
 #include <linux/init.h>
@@ -167,30 +167,33 @@ extern int safe_smp_processor_id(void);
 
 #ifdef CONFIG_X86_LOCAL_APIC
 
+#ifndef CONFIG_X86_64
 static inline int logical_smp_processor_id(void)
 {
        /* we don't want to mark this access volatile - bad code generation */
        return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
 }
 
-#ifndef CONFIG_X86_64
+#include <mach_apicdef.h>
 static inline unsigned int read_apic_id(void)
 {
-       return *(u32 *)(APIC_BASE + APIC_ID);
+       unsigned int reg;
+
+       reg = *(u32 *)(APIC_BASE + APIC_ID);
+
+       return GET_APIC_ID(reg);
 }
-#else
-extern unsigned int read_apic_id(void);
 #endif
 
 
-# ifdef APIC_DEFINITION
+# if defined(APIC_DEFINITION) || defined(CONFIG_X86_64)
 extern int hard_smp_processor_id(void);
 # else
-#  include <mach_apicdef.h>
+#include <mach_apicdef.h>
 static inline int hard_smp_processor_id(void)
 {
        /* we don't want to mark this access volatile - bad code generation */
-       return GET_APIC_ID(read_apic_id());
+       return read_apic_id();
 }
 # endif /* APIC_DEFINITION */
 
@@ -207,4 +210,4 @@ extern void cpu_uninit(void);
 #endif
 
 #endif /* __ASSEMBLY__ */
-#endif
+#endif /* ASM_X86__SMP_H */
index 80af9c4ccad7f05cd09db4d0d212ec2a0753ed04..db73274c83c3b3ea302dff7a233fab452745c838 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
+#ifndef ASM_X86__SOCKET_H
+#define ASM_X86__SOCKET_H
 
 #include <asm/sockios.h>
 
@@ -54,4 +54,4 @@
 
 #define SO_MARK                        36
 
-#endif /* _ASM_SOCKET_H */
+#endif /* ASM_X86__SOCKET_H */
index 49cc72b5d3c914fa5bb98f181e37768018cc6782..a006704fdc8427cf4b4cd134bf9695375dbc3af5 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SOCKIOS_H
-#define _ASM_X86_SOCKIOS_H
+#ifndef ASM_X86__SOCKIOS_H
+#define ASM_X86__SOCKIOS_H
 
 /* Socket-level I/O control calls. */
 #define FIOSETOWN      0x8901
@@ -10,4 +10,4 @@
 #define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
 #define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
 
-#endif /* _ASM_X86_SOCKIOS_H */
+#endif /* ASM_X86__SOCKIOS_H */
index 9bd48b0a534ba7b76ffeb439e9276af540a35081..38f8e6bc3186bb52ce64245870d651f20c24d6fd 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SPARSEMEM_H
-#define _ASM_X86_SPARSEMEM_H
+#ifndef ASM_X86__SPARSEMEM_H
+#define ASM_X86__SPARSEMEM_H
 
 #ifdef CONFIG_SPARSEMEM
 /*
@@ -31,4 +31,4 @@
 #endif
 
 #endif /* CONFIG_SPARSEMEM */
-#endif
+#endif /* ASM_X86__SPARSEMEM_H */
index 4f9a9861799ac648d406856a8a5ed1881e678a25..cbe01086ba640e4af05ad1b32a8f2bad2ae3699e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _X86_SPINLOCK_H_
-#define _X86_SPINLOCK_H_
+#ifndef ASM_X86__SPINLOCK_H
+#define ASM_X86__SPINLOCK_H
 
 #include <asm/atomic.h>
 #include <asm/rwlock.h>
@@ -366,4 +366,4 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
 #define _raw_read_relax(lock)  cpu_relax()
 #define _raw_write_relax(lock) cpu_relax()
 
-#endif
+#endif /* ASM_X86__SPINLOCK_H */
index 06c071c9eee9f1d2e5288930b91e511a3d094d61..6aa9b562c5080ae0ac7295a0adefea9ff31c138b 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_SPINLOCK_TYPES_H
-#define __ASM_SPINLOCK_TYPES_H
+#ifndef ASM_X86__SPINLOCK_TYPES_H
+#define ASM_X86__SPINLOCK_TYPES_H
 
 #ifndef __LINUX_SPINLOCK_TYPES_H
 # error "please don't include this file directly"
@@ -17,4 +17,4 @@ typedef struct {
 
 #define __RAW_RW_LOCK_UNLOCKED         { RW_LOCK_BIAS }
 
-#endif
+#endif /* ASM_X86__SPINLOCK_TYPES_H */
index 774c919dc2323cb7ecb85b1350876146414286db..5363e4f7e1cddb7b52f0db52be72eb185f5a2a5a 100644 (file)
@@ -24,8 +24,8 @@
  * Send feedback to Pat Gaughen <gone@us.ibm.com>
  */
 
-#ifndef _ASM_SRAT_H_
-#define _ASM_SRAT_H_
+#ifndef ASM_X86__SRAT_H
+#define ASM_X86__SRAT_H
 
 #ifdef CONFIG_ACPI_NUMA
 extern int get_memcfg_from_srat(void);
@@ -36,4 +36,4 @@ static inline int get_memcfg_from_srat(void)
 }
 #endif
 
-#endif /* _ASM_SRAT_H_ */
+#endif /* ASM_X86__SRAT_H */
index 30f82526a8e285547ea890febb757890d3ad4cde..f43517e28532fd930a6cf017591ac7f1bee5febc 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_STACKTRACE_H
-#define _ASM_STACKTRACE_H 1
+#ifndef ASM_X86__STACKTRACE_H
+#define ASM_X86__STACKTRACE_H
 
 extern int kstack_depth_to_print;
 
@@ -18,4 +18,4 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
                unsigned long *stack, unsigned long bp,
                const struct stacktrace_ops *ops, void *data);
 
-#endif
+#endif /* ASM_X86__STACKTRACE_H */
index 5c22dcb5d17e2e49fcae06e6b86db425730dcbad..1e120f62890546f58311c213d8f46d8ec2f0d065 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_STAT_H
-#define _ASM_X86_STAT_H
+#ifndef ASM_X86__STAT_H
+#define ASM_X86__STAT_H
 
 #define STAT_HAVE_NSEC 1
 
@@ -111,4 +111,4 @@ struct __old_kernel_stat {
 #endif
 };
 
-#endif
+#endif /* ASM_X86__STAT_H */
index 7c651aa972527928788a63648b567bf8bd70aec7..3f005bc3aa5bb0e35c6421927f6ad999d8181a1f 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_STATFS_H
-#define _ASM_X86_STATFS_H
+#ifndef ASM_X86__STATFS_H
+#define ASM_X86__STATFS_H
 
 #ifdef __i386__
 #include <asm-generic/statfs.h>
@@ -60,4 +60,4 @@ struct compat_statfs64 {
 } __attribute__((packed));
 
 #endif /* !__i386__ */
-#endif
+#endif /* ASM_X86__STATFS_H */
index 193578cd1fd98af422fb5146c110ca03625d26cb..487843ed245a54bd91dadaca58413b650b0976cb 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _I386_STRING_H_
-#define _I386_STRING_H_
+#ifndef ASM_X86__STRING_32_H
+#define ASM_X86__STRING_32_H
 
 #ifdef __KERNEL__
 
@@ -323,4 +323,4 @@ extern void *memscan(void *addr, int c, size_t size);
 
 #endif /* __KERNEL__ */
 
-#endif
+#endif /* ASM_X86__STRING_32_H */
index 52b5ab383395fde07df5e4d71f8899c8982d26b2..a2add11d3b66a6424f528cd365aaf6818db9556a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _X86_64_STRING_H_
-#define _X86_64_STRING_H_
+#ifndef ASM_X86__STRING_64_H
+#define ASM_X86__STRING_64_H
 
 #ifdef __KERNEL__
 
@@ -57,4 +57,4 @@ int strcmp(const char *cs, const char *ct);
 
 #endif /* __KERNEL__ */
 
-#endif
+#endif /* ASM_X86__STRING_64_H */
similarity index 94%
rename from include/asm-x86/mach-summit/mach_apic.h
rename to include/asm-x86/summit/apic.h
index c47e2ab5c5ca06515c87b7a320e42fccff3e8ed2..c5b2e4b10358dd6beda71fb8b5a318d9ee341dff 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_APIC_H
-#define __ASM_MACH_APIC_H
+#ifndef __ASM_SUMMIT_APIC_H
+#define __ASM_SUMMIT_APIC_H
 
 #include <asm/smp.h>
 
@@ -21,7 +21,7 @@ static inline cpumask_t target_cpus(void)
         * Just start on cpu 0.  IRQ balancing will spread load
         */
        return cpumask_of_cpu(0);
-} 
+}
 #define TARGET_CPUS    (target_cpus())
 
 #define INT_DELIVERY_MODE (dest_LowestPrio)
@@ -30,10 +30,10 @@ static inline cpumask_t target_cpus(void)
 static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
 {
        return 0;
-} 
+}
 
 /* we don't use the phys_cpu_present_map to indicate apicid presence */
-static inline unsigned long check_apicid_present(int bit) 
+static inline unsigned long check_apicid_present(int bit)
 {
        return 1;
 }
@@ -122,7 +122,7 @@ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_id_map)
 
 static inline physid_mask_t apicid_to_cpu_present(int apicid)
 {
-       return physid_mask_of_physid(apicid);
+       return physid_mask_of_physid(0);
 }
 
 static inline void setup_portio_remap(void)
@@ -143,22 +143,22 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
        int num_bits_set;
        int cpus_found = 0;
        int cpu;
-       int apicid;     
+       int apicid;
 
        num_bits_set = cpus_weight(cpumask);
        /* Return id to all */
        if (num_bits_set == NR_CPUS)
                return (int) 0xFF;
-       /* 
-        * The cpus in the mask must all be on the apic cluster.  If are not 
-        * on the same apicid cluster return default value of TARGET_CPUS. 
+       /*
+        * The cpus in the mask must all be on the apic cluster.  If are not
+        * on the same apicid cluster return default value of TARGET_CPUS.
         */
        cpu = first_cpu(cpumask);
        apicid = cpu_to_logical_apicid(cpu);
        while (cpus_found < num_bits_set) {
                if (cpu_isset(cpu, cpumask)) {
                        int new_apicid = cpu_to_logical_apicid(cpu);
-                       if (apicid_cluster(apicid) != 
+                       if (apicid_cluster(apicid) !=
                                        apicid_cluster(new_apicid)){
                                printk ("%s: Not a valid mask!\n",__FUNCTION__);
                                return 0xFF;
@@ -182,4 +182,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
        return hard_smp_processor_id() >> index_msb;
 }
 
-#endif /* __ASM_MACH_APIC_H */
+#endif /* __ASM_SUMMIT_APIC_H */
diff --git a/include/asm-x86/summit/apicdef.h b/include/asm-x86/summit/apicdef.h
new file mode 100644 (file)
index 0000000..f3fbca1
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __ASM_SUMMIT_APICDEF_H
+#define __ASM_SUMMIT_APICDEF_H
+
+#define                APIC_ID_MASK            (0xFF<<24)
+
+static inline unsigned get_apic_id(unsigned long x)
+{
+       return (x>>24)&0xFF;
+}
+
+#define                GET_APIC_ID(x)  get_apic_id(x)
+
+#endif
similarity index 83%
rename from include/asm-x86/mach-summit/mach_ipi.h
rename to include/asm-x86/summit/ipi.h
index 9404c535b7ecbbf6f496d0cd80f4eb266a529208..53bd1e7bd7b448ac2d1f6ff3a25a496dc9c16358 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_IPI_H
-#define __ASM_MACH_IPI_H
+#ifndef __ASM_SUMMIT_IPI_H
+#define __ASM_SUMMIT_IPI_H
 
 void send_IPI_mask_sequence(cpumask_t mask, int vector);
 
@@ -22,4 +22,4 @@ static inline void send_IPI_all(int vector)
        send_IPI_mask(cpu_online_map, vector);
 }
 
-#endif /* __ASM_MACH_IPI_H */
+#endif /* __ASM_SUMMIT_IPI_H */
similarity index 96%
rename from include/asm-x86/mach-summit/mach_mpparse.h
rename to include/asm-x86/summit/mpparse.h
index fdf5917013399d9175253ddf587e440c2caea654..013ce6fab2d5306c30023cc53d0f7c939cca4840 100644 (file)
@@ -1,7 +1,6 @@
-#ifndef __ASM_MACH_MPPARSE_H
-#define __ASM_MACH_MPPARSE_H
+#ifndef __ASM_SUMMIT_MPPARSE_H
+#define __ASM_SUMMIT_MPPARSE_H
 
-#include <mach_apic.h>
 #include <asm/tsc.h>
 
 extern int use_cyclone;
@@ -12,11 +11,11 @@ extern void setup_summit(void);
 #define setup_summit() {}
 #endif
 
-static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, 
+static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
                char *productid)
 {
-       if (!strncmp(oem, "IBM ENSW", 8) && 
-                       (!strncmp(productid, "VIGIL SMP", 9) 
+       if (!strncmp(oem, "IBM ENSW", 8) &&
+                       (!strncmp(productid, "VIGIL SMP", 9)
                         || !strncmp(productid, "EXA", 3)
                         || !strncmp(productid, "RUTHLESS SMP", 12))){
                mark_tsc_unstable("Summit based system");
@@ -107,4 +106,4 @@ static inline int is_WPEG(struct rio_detail *rio){
                rio->type == LookOutAWPEG || rio->type == LookOutBWPEG);
 }
 
-#endif /* __ASM_MACH_MPPARSE_H */
+#endif /* __ASM_SUMMIT_MPPARSE_H */
index 8675c6782a7da2754a4b391bab931b920db9a009..acb6d4d491f4d35b704b2dac6e52ce21cb409161 100644 (file)
@@ -3,8 +3,8 @@
  * Based on code
  * Copyright 2001 Patrick Mochel <mochel@osdl.org>
  */
-#ifndef __ASM_X86_32_SUSPEND_H
-#define __ASM_X86_32_SUSPEND_H
+#ifndef ASM_X86__SUSPEND_32_H
+#define ASM_X86__SUSPEND_32_H
 
 #include <asm/desc.h>
 #include <asm/i387.h>
@@ -48,4 +48,4 @@ static inline void acpi_save_register_state(unsigned long return_point)
 extern int acpi_save_state_mem(void);
 #endif
 
-#endif /* __ASM_X86_32_SUSPEND_H */
+#endif /* ASM_X86__SUSPEND_32_H */
index dc3262b4307291bffd206e4c015d9743ae8d0a33..cf821dd310e81c9bf8858452188f70152bfe17a3 100644 (file)
@@ -3,8 +3,8 @@
  * Based on code
  * Copyright 2001 Patrick Mochel <mochel@osdl.org>
  */
-#ifndef __ASM_X86_64_SUSPEND_H
-#define __ASM_X86_64_SUSPEND_H
+#ifndef ASM_X86__SUSPEND_64_H
+#define ASM_X86__SUSPEND_64_H
 
 #include <asm/desc.h>
 #include <asm/i387.h>
@@ -49,4 +49,4 @@ extern int acpi_save_state_mem(void);
 extern char core_restore_code;
 extern char restore_registers;
 
-#endif /* __ASM_X86_64_SUSPEND_H */
+#endif /* ASM_X86__SUSPEND_64_H */
index 2730b351afcf2422695ca176cf8a7edbee57b9cc..1e20adbcad4b0cff70243b4ed71c7182e2371c64 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_SWIOTLB_H
-#define _ASM_SWIOTLB_H 1
+#ifndef ASM_X86__SWIOTLB_H
+#define ASM_X86__SWIOTLB_H
 
 #include <asm/dma-mapping.h>
 
@@ -55,4 +55,4 @@ static inline void pci_swiotlb_init(void)
 
 static inline void dma_mark_clean(void *addr, size_t size) {}
 
-#endif /* _ASM_SWIOTLB_H */
+#endif /* ASM_X86__SWIOTLB_H */
index b47a1d0b8a834719866a713dadf65a28fd566a4c..b689bee71104da4ba5b9eff3fa597606cfdd9de3 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _I386_SYNC_BITOPS_H
-#define _I386_SYNC_BITOPS_H
+#ifndef ASM_X86__SYNC_BITOPS_H
+#define ASM_X86__SYNC_BITOPS_H
 
 /*
  * Copyright 1992, Linus Torvalds.
@@ -127,4 +127,4 @@ static inline int sync_test_and_change_bit(int nr, volatile unsigned long *addr)
 
 #undef ADDR
 
-#endif /* _I386_SYNC_BITOPS_H */
+#endif /* ASM_X86__SYNC_BITOPS_H */
index 983ce37c491fd83504fd0a82ff3a7da15f608861..34505dd7b24de4ad67b968f93b3fc24156700206 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_SYSTEM_H_
-#define _ASM_X86_SYSTEM_H_
+#ifndef ASM_X86__SYSTEM_H
+#define ASM_X86__SYSTEM_H
 
 #include <asm/asm.h>
 #include <asm/segment.h>
@@ -419,4 +419,4 @@ static inline void rdtsc_barrier(void)
        alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
 }
 
-#endif
+#endif /* ASM_X86__SYSTEM_H */
index 97fa251ccb2b088d055e0332fb97d50e5aeb480d..5aedb8bffc5a0c50fc3e6ac4576efc4686a94b37 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_SYSTEM_H
-#define __ASM_SYSTEM_H
+#ifndef ASM_X86__SYSTEM_64_H
+#define ASM_X86__SYSTEM_64_H
 
 #include <asm/segment.h>
 #include <asm/cmpxchg.h>
@@ -19,4 +19,4 @@ static inline void write_cr8(unsigned long val)
 
 #include <linux/irqflags.h>
 
-#endif
+#endif /* ASM_X86__SYSTEM_64_H */
index b1a4ea00df783cb86ea52818fb148c4d86a31ae3..e7932d7fbbab9d10ccff23b170f54d20a9e15a32 100644 (file)
@@ -21,8 +21,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#ifndef _ASM_X86_64_TCE_H
-#define _ASM_X86_64_TCE_H
+#ifndef ASM_X86__TCE_H
+#define ASM_X86__TCE_H
 
 extern unsigned int specified_table_size;
 struct iommu_table;
@@ -45,4 +45,4 @@ extern void * __init alloc_tce_table(void);
 extern void __init free_tce_table(void *tbl);
 extern int __init build_tce_table(struct pci_dev *dev, void __iomem *bbar);
 
-#endif /* _ASM_X86_64_TCE_H */
+#endif /* ASM_X86__TCE_H */
index af1b70ea440fe2e4d6fded733d86a91bcb4d89af..3d00dc5e0c717967fb0b5a73663df7850c695a58 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_TERMBITS_H
-#define _ASM_X86_TERMBITS_H
+#ifndef ASM_X86__TERMBITS_H
+#define ASM_X86__TERMBITS_H
 
 #include <linux/posix_types.h>
 
@@ -195,4 +195,4 @@ struct ktermios {
 #define        TCSADRAIN       1
 #define        TCSAFLUSH       2
 
-#endif /* _ASM_X86_TERMBITS_H */
+#endif /* ASM_X86__TERMBITS_H */
index f72956331c49349623014bffc4c241f01c361eee..e235db248071f4cbc14a881049e215b2ab6bd038 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_TERMIOS_H
-#define _ASM_X86_TERMIOS_H
+#ifndef ASM_X86__TERMIOS_H
+#define ASM_X86__TERMIOS_H
 
 #include <asm/termbits.h>
 #include <asm/ioctls.h>
@@ -110,4 +110,4 @@ static inline int kernel_termios_to_user_termios_1(struct termios __user *u,
 
 #endif /* __KERNEL__ */
 
-#endif /* _ASM_X86_TERMIOS_H */
+#endif /* ASM_X86__TERMIOS_H */
index 399bf6026b16c8fd8f17a9fcf154653321495c7a..1c7f57b6b66e413ae52bda3d2c4162703870aed0 100644 (file)
@@ -1,9 +1,9 @@
-#ifndef __ASM_I386_THERM_THROT_H__
-#define __ASM_I386_THERM_THROT_H__ 1
+#ifndef ASM_X86__THERM_THROT_H
+#define ASM_X86__THERM_THROT_H
 
 #include <asm/atomic.h>
 
 extern atomic_t therm_throt_en;
 int therm_throt_process(int curr);
 
-#endif /* __ASM_I386_THERM_THROT_H__ */
+#endif /* ASM_X86__THERM_THROT_H */
index da0a675adf94a1a753792d1bca54c45d4fe3bed4..e64be8863b762fc49e3b89829d6b7ca87d034e43 100644 (file)
@@ -4,8 +4,8 @@
  * - Incorporating suggestions made by Linus Torvalds and Dave Miller
  */
 
-#ifndef _ASM_X86_THREAD_INFO_H
-#define _ASM_X86_THREAD_INFO_H
+#ifndef ASM_X86__THREAD_INFO_H
+#define ASM_X86__THREAD_INFO_H
 
 #include <linux/compiler.h>
 #include <asm/page.h>
@@ -258,4 +258,4 @@ extern void free_thread_info(struct thread_info *ti);
 extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
 #define arch_task_cache_init arch_task_cache_init
 #endif
-#endif /* _ASM_X86_THREAD_INFO_H */
+#endif /* ASM_X86__THREAD_INFO_H */
index 5f4fc3e02387358b8246de6d50eba15341155573..3e724eef7ac468f118bb8c7c95edac31577cc739 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASMX86_TIME_H
-#define _ASMX86_TIME_H
+#ifndef ASM_X86__TIME_H
+#define ASM_X86__TIME_H
 
 extern void hpet_time_init(void);
 
@@ -60,4 +60,4 @@ extern void time_init(void);
 
 extern unsigned long __init calibrate_cpu(void);
 
-#endif
+#endif /* ASM_X86__TIME_H */
index 2a8a92d5787b4cb85e75e8feb6334fb9c9ca868e..d0babce4b47a6ecbc9d3ca62bf084665c49a02b9 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASMi386_TIMER_H
-#define _ASMi386_TIMER_H
+#ifndef ASM_X86__TIMER_H
+#define ASM_X86__TIMER_H
 #include <linux/init.h>
 #include <linux/pm.h>
 #include <linux/percpu.h>
@@ -63,4 +63,4 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc)
        return ns;
 }
 
-#endif
+#endif /* ASM_X86__TIMER_H */
index 43e5a78500c57905fa8c24f5397f37a86a13fd7a..d1ce2416a5da14e61d151150622e4dbe7491c866 100644 (file)
@@ -1,6 +1,6 @@
 /* x86 architecture timex specifications */
-#ifndef _ASM_X86_TIMEX_H
-#define _ASM_X86_TIMEX_H
+#ifndef ASM_X86__TIMEX_H
+#define ASM_X86__TIMEX_H
 
 #include <asm/processor.h>
 #include <asm/tsc.h>
@@ -16,4 +16,4 @@
 
 #define ARCH_HAS_READ_CURRENT_TIMER
 
-#endif
+#endif /* ASM_X86__TIMEX_H */
index e4e9e2d07a93194b0ec45a5c4863464bfe1b333c..db36e9e89e873c7d65a2115c119ec7d828aa6133 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_TLB_H
-#define _ASM_X86_TLB_H
+#ifndef ASM_X86__TLB_H
+#define ASM_X86__TLB_H
 
 #define tlb_start_vma(tlb, vma) do { } while (0)
 #define tlb_end_vma(tlb, vma) do { } while (0)
@@ -8,4 +8,4 @@
 
 #include <asm-generic/tlb.h>
 
-#endif
+#endif /* ASM_X86__TLB_H */
index 35c76ceb9f4055eb548da359319a687467e73f66..ef68b76dc3c5c32f0ee2f24a1ecfec5725bba003 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_TLBFLUSH_H
-#define _ASM_X86_TLBFLUSH_H
+#ifndef ASM_X86__TLBFLUSH_H
+#define ASM_X86__TLBFLUSH_H
 
 #include <linux/mm.h>
 #include <linux/sched.h>
@@ -165,4 +165,4 @@ static inline void flush_tlb_kernel_range(unsigned long start,
        flush_tlb_all();
 }
 
-#endif /* _ASM_X86_TLBFLUSH_H */
+#endif /* ASM_X86__TLBFLUSH_H */
index 90ac7718469a5b416bfd90350b24ade716698925..7eca9bc022b2dd40568f6ff963dcd271a17de616 100644 (file)
@@ -22,8 +22,8 @@
  *
  * Send feedback to <colpatch@us.ibm.com>
  */
-#ifndef _ASM_X86_TOPOLOGY_H
-#define _ASM_X86_TOPOLOGY_H
+#ifndef ASM_X86__TOPOLOGY_H
+#define ASM_X86__TOPOLOGY_H
 
 #ifdef CONFIG_X86_32
 # ifdef CONFIG_X86_HT
@@ -255,4 +255,4 @@ static inline void set_mp_bus_to_node(int busnum, int node)
 }
 #endif
 
-#endif /* _ASM_X86_TOPOLOGY_H */
+#endif /* ASM_X86__TOPOLOGY_H */
index b156b08d0131a895b4b3d3a7034be45650220e16..0406bbd898a9601efbb5af853340712ed53e19a9 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __TRAMPOLINE_HEADER
-#define __TRAMPOLINE_HEADER
+#ifndef ASM_X86__TRAMPOLINE_H
+#define ASM_X86__TRAMPOLINE_H
 
 #ifndef __ASSEMBLY__
 
@@ -18,4 +18,4 @@ extern unsigned long setup_trampoline(void);
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* __TRAMPOLINE_HEADER */
+#endif /* ASM_X86__TRAMPOLINE_H */
index b60fab546da7625d388e3c8d085dfa266fee7b01..2ccebc6fb0b0143c9605ab548662718dacb8b97d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_TRAPS_H
-#define _ASM_X86_TRAPS_H
+#ifndef ASM_X86__TRAPS_H
+#define ASM_X86__TRAPS_H
 
 /* Common in X86_32 and X86_64 */
 asmlinkage void divide_error(void);
@@ -67,4 +67,4 @@ asmlinkage void do_spurious_interrupt_bug(struct pt_regs *);
 asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code);
 
 #endif /* CONFIG_X86_32 */
-#endif /* _ASM_X86_TRAPS_H */
+#endif /* ASM_X86__TRAPS_H */
index cb6f6ee45b8f858921ad4cfbcaf1f3f0d6f886a2..ad0f5c41e78cde2ba21c653cc4a159faed9e27d7 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * x86 TSC related functions
  */
-#ifndef _ASM_X86_TSC_H
-#define _ASM_X86_TSC_H
+#ifndef ASM_X86__TSC_H
+#define ASM_X86__TSC_H
 
 #include <asm/processor.h>
 
@@ -59,4 +59,4 @@ extern void check_tsc_sync_target(void);
 
 extern int notsc_setup(char *);
 
-#endif
+#endif /* ASM_X86__TSC_H */
index 1ac80cd9acf8599a143ce5cf98913b91a668eda7..e78b52e17444ac245618369c52d34514805481f9 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_TYPES_H
-#define _ASM_X86_TYPES_H
+#ifndef ASM_X86__TYPES_H
+#define ASM_X86__TYPES_H
 
 #include <asm-generic/int-ll64.h>
 
@@ -33,4 +33,4 @@ typedef u32 dma_addr_t;
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 
-#endif
+#endif /* ASM_X86__TYPES_H */
index 5f702d1d52184424941d3238ee82597c9f05ce37..48ebc0ad40ec17b66b700812c5c4792662227a8f 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_UACCES_H_
-#define _ASM_UACCES_H_
+#ifndef ASM_X86__UACCESS_H
+#define ASM_X86__UACCESS_H
 /*
  * User space memory access functions
  */
@@ -450,5 +450,5 @@ extern struct movsl_mask {
 # include "uaccess_64.h"
 #endif
 
-#endif
+#endif /* ASM_X86__UACCESS_H */
 
index 6fdef39a0bcb849d86e3bb0e1ade448694d21cdb..6b5b57d9c6d1f9ee55cf15cebf75090696c63f45 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __i386_UACCESS_H
-#define __i386_UACCESS_H
+#ifndef ASM_X86__UACCESS_32_H
+#define ASM_X86__UACCESS_32_H
 
 /*
  * User space memory access functions
@@ -215,4 +215,4 @@ long strnlen_user(const char __user *str, long n);
 unsigned long __must_check clear_user(void __user *mem, unsigned long len);
 unsigned long __must_check __clear_user(void __user *mem, unsigned long len);
 
-#endif /* __i386_UACCESS_H */
+#endif /* ASM_X86__UACCESS_32_H */
index 515d4dce96b598bc6e9d07dba21332a44924948c..5cfd2951c9e786ceb7c897e64c858b81eeabfc07 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __X86_64_UACCESS_H
-#define __X86_64_UACCESS_H
+#ifndef ASM_X86__UACCESS_64_H
+#define ASM_X86__UACCESS_64_H
 
 /*
  * User space memory access functions
@@ -198,4 +198,4 @@ static inline int __copy_from_user_inatomic_nocache(void *dst,
 unsigned long
 copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest);
 
-#endif /* __X86_64_UACCESS_H */
+#endif /* ASM_X86__UACCESS_64_H */
index 50a79f7fcde9e42f85fe825553b3efbd60791371..9948dd328084ef66461d2dc92c996235fc78eb5e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_UCONTEXT_H
-#define _ASM_X86_UCONTEXT_H
+#ifndef ASM_X86__UCONTEXT_H
+#define ASM_X86__UCONTEXT_H
 
 struct ucontext {
        unsigned long     uc_flags;
@@ -9,4 +9,4 @@ struct ucontext {
        sigset_t          uc_sigmask;   /* mask last for extensibility */
 };
 
-#endif /* _ASM_X86_UCONTEXT_H */
+#endif /* ASM_X86__UCONTEXT_H */
index a7bd416b4763832f0a9851df49e92c938b8c5232..59dcdec37160a02127780c1b7f9a76743c2041e0 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_UNALIGNED_H
-#define _ASM_X86_UNALIGNED_H
+#ifndef ASM_X86__UNALIGNED_H
+#define ASM_X86__UNALIGNED_H
 
 /*
  * The x86 can do unaligned accesses itself.
@@ -11,4 +11,4 @@
 #define get_unaligned __get_unaligned_le
 #define put_unaligned __put_unaligned_le
 
-#endif /* _ASM_X86_UNALIGNED_H */
+#endif /* ASM_X86__UNALIGNED_H */
index d7394673b772442677ed3ec7063a4ea384ad7b62..017f4a87c9132bbce98f194b55d80c95ea3bfd65 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_I386_UNISTD_H_
-#define _ASM_I386_UNISTD_H_
+#ifndef ASM_X86__UNISTD_32_H
+#define ASM_X86__UNISTD_32_H
 
 /*
  * This file contains the system call numbers.
 #endif
 
 #endif /* __KERNEL__ */
-#endif /* _ASM_I386_UNISTD_H_ */
+#endif /* ASM_X86__UNISTD_32_H */
index 3a341d791792ad41999893f7034e529cce28e880..ace83f1f678730134569f1efb3656a1d869156d4 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_64_UNISTD_H_
-#define _ASM_X86_64_UNISTD_H_
+#ifndef ASM_X86__UNISTD_64_H
+#define ASM_X86__UNISTD_64_H
 
 #ifndef __SYSCALL
 #define __SYSCALL(a, b)
@@ -690,4 +690,4 @@ __SYSCALL(__NR_inotify_init1, sys_inotify_init1)
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif /* __KERNEL__ */
 
-#endif /* _ASM_X86_64_UNISTD_H_ */
+#endif /* ASM_X86__UNISTD_64_H */
index 8b064bd9c5535fa741c404b6e202445a8a9a003b..a2151567db44388a2465bc32924f7399942a821d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_UNWIND_H
-#define _ASM_X86_UNWIND_H
+#ifndef ASM_X86__UNWIND_H
+#define ASM_X86__UNWIND_H
 
 #define UNW_PC(frame) ((void)(frame), 0UL)
 #define UNW_SP(frame) ((void)(frame), 0UL)
@@ -10,4 +10,4 @@ static inline int arch_unw_user_mode(const void *info)
        return 0;
 }
 
-#endif /* _ASM_X86_UNWIND_H */
+#endif /* ASM_X86__UNWIND_H */
index a3d91004787924876ea3dd0a137c5c710b7f0051..aa66c1857f06580e80160b5f8c4f1a1d0495b1df 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef USER32_H
-#define USER32_H 1
+#ifndef ASM_X86__USER32_H
+#define ASM_X86__USER32_H
 
 /* IA32 compatible user structures for ptrace.
  * These should be used for 32bit coredumps too. */
@@ -67,4 +67,4 @@ struct user32 {
 };
 
 
-#endif
+#endif /* ASM_X86__USER32_H */
index d6e51edc259d909dd78035b6de1775861a86ead1..e0fe2f55f1a6c736bcc2e568b9f355c50ede638c 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _I386_USER_H
-#define _I386_USER_H
+#ifndef ASM_X86__USER_32_H
+#define ASM_X86__USER_32_H
 
 #include <asm/page.h>
 /* Core file format: The core file is written in such a way that gdb
@@ -128,4 +128,4 @@ struct user{
 #define HOST_TEXT_START_ADDR (u.start_code)
 #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
 
-#endif /* _I386_USER_H */
+#endif /* ASM_X86__USER_32_H */
index 6037b634c77fd374ae744b2816e2c4765ad7ec4a..38b5799863b455ecd911ceb23685a9ec5bcde74b 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _X86_64_USER_H
-#define _X86_64_USER_H
+#ifndef ASM_X86__USER_64_H
+#define ASM_X86__USER_64_H
 
 #include <asm/types.h>
 #include <asm/page.h>
@@ -134,4 +134,4 @@ struct user {
 #define HOST_TEXT_START_ADDR (u.start_code)
 #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
 
-#endif /* _X86_64_USER_H */
+#endif /* ASM_X86__USER_64_H */
index aa73362ff5dff48d17c4c36a6339dcb22fe0d3bf..7cd6d7ec1308fe523811d462865951a8667d7ab0 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_BIOS_H
-#define _ASM_X86_BIOS_H
+#ifndef ASM_X86__UV__BIOS_H
+#define ASM_X86__UV__BIOS_H
 
 /*
  * BIOS layer definitions.
@@ -65,4 +65,4 @@ x86_bios_freq_base(unsigned long which, unsigned long *ticks_per_second,
                   unsigned long *drift_info);
 extern const char *x86_bios_strerror(long status);
 
-#endif /* _ASM_X86_BIOS_H */
+#endif /* ASM_X86__UV__BIOS_H */
index 91ac0dfb758805b052bba15f63796243fc4b9fab..0950239acaf61014f2564f4887c269ed3c011476 100644 (file)
@@ -8,8 +8,8 @@
  * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved.
  */
 
-#ifndef __ASM_X86_UV_BAU__
-#define __ASM_X86_UV_BAU__
+#ifndef ASM_X86__UV__UV_BAU_H
+#define ASM_X86__UV__UV_BAU_H
 
 #include <linux/bitmap.h>
 #define BITSPERBYTE 8
@@ -334,4 +334,4 @@ extern int uv_flush_tlb_others(cpumask_t *, struct mm_struct *, unsigned long);
 extern void uv_bau_message_intr1(void);
 extern void uv_bau_timeout_intr1(void);
 
-#endif /* __ASM_X86_UV_BAU__ */
+#endif /* ASM_X86__UV__UV_BAU_H */
index a4ef26e5850bb445e5dfa5493b1778ee85feb771..bdb5b01afbf591d66f5b1ec87ee859886459f594 100644 (file)
@@ -8,8 +8,8 @@
  * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved.
  */
 
-#ifndef __ASM_X86_UV_HUB_H__
-#define __ASM_X86_UV_HUB_H__
+#ifndef ASM_X86__UV__UV_HUB_H
+#define ASM_X86__UV__UV_HUB_H
 
 #include <linux/numa.h>
 #include <linux/percpu.h>
@@ -350,5 +350,5 @@ static inline int uv_num_possible_blades(void)
        return uv_possible_blades;
 }
 
-#endif /* __ASM_X86_UV_HUB__ */
+#endif /* ASM_X86__UV__UV_HUB_H */
 
index 151fd7fcb809138d3454c50f023de8b1b49d5335..8b03d89d2459e8f3664bf1dbca34593b40457407 100644 (file)
@@ -8,8 +8,8 @@
  * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved.
  */
 
-#ifndef __ASM_X86_UV_MMRS__
-#define __ASM_X86_UV_MMRS__
+#ifndef ASM_X86__UV__UV_MMRS_H
+#define ASM_X86__UV__UV_MMRS_H
 
 #define UV_MMR_ENABLE          (1UL << 63)
 
@@ -1292,4 +1292,4 @@ union uvh_si_alias2_overlay_config_u {
 };
 
 
-#endif /* __ASM_X86_UV_MMRS__ */
+#endif /* ASM_X86__UV__UV_MMRS_H */
index 8e18fb80f5e641ac3683b8c84c68cb511c4ab30f..4ab320913ea3abcef82fc8313127501249a201bb 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_VDSO_H
-#define _ASM_X86_VDSO_H        1
+#ifndef ASM_X86__VDSO_H
+#define ASM_X86__VDSO_H
 
 #ifdef CONFIG_X86_64
 extern const char VDSO64_PRELINK[];
@@ -44,4 +44,4 @@ extern const char vdso32_int80_start, vdso32_int80_end;
 extern const char vdso32_syscall_start, vdso32_syscall_end;
 extern const char vdso32_sysenter_start, vdso32_sysenter_end;
 
-#endif /* asm-x86/vdso.h */
+#endif /* ASM_X86__VDSO_H */
index 0ccf804377e600b7014a7247f964b8b83a4dd058..b9e493d07d07a1478ec8d42538cf55fe54e3b970 100644 (file)
@@ -4,8 +4,8 @@
  *     (c) 1998 Martin Mares <mj@ucw.cz>
  */
 
-#ifndef _LINUX_ASM_VGA_H_
-#define _LINUX_ASM_VGA_H_
+#ifndef ASM_X86__VGA_H
+#define ASM_X86__VGA_H
 
 /*
  *     On the PC, we can just recalculate addresses and then
@@ -17,4 +17,4 @@
 #define vga_readb(x) (*(x))
 #define vga_writeb(x, y) (*(y) = (x))
 
-#endif
+#endif /* ASM_X86__VGA_H */
index 3301f092934291427d1505c056b636cdd2fe8148..38fd133640211790b4dfe3e0b31a7f171d52e88c 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_VGTOD_H
-#define _ASM_VGTOD_H 1
+#ifndef ASM_X86__VGTOD_H
+#define ASM_X86__VGTOD_H
 
 #include <asm/vsyscall.h>
 #include <linux/clocksource.h>
@@ -26,4 +26,4 @@ extern struct vsyscall_gtod_data __vsyscall_gtod_data
 __section_vsyscall_gtod_data;
 extern struct vsyscall_gtod_data vsyscall_gtod_data;
 
-#endif
+#endif /* ASM_X86__VGTOD_H */
index 995258831b7f8dbf5a97b37315a0676eda7f8426..9627a8fe84e9275a28728fd81158ff465ac1cba9 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __I386_SGI_COBALT_H
-#define __I386_SGI_COBALT_H
+#ifndef ASM_X86__VISWS__COBALT_H
+#define ASM_X86__VISWS__COBALT_H
 
 #include <asm/fixmap.h>
 
@@ -122,4 +122,4 @@ extern char visws_board_type;
 
 extern char visws_board_rev;
 
-#endif /* __I386_SGI_COBALT_H */
+#endif /* ASM_X86__VISWS__COBALT_H */
index dfcd4f07ab85b9e6a1c839de753bb242eb8076c4..b36d3b378c6353dd2c62811ae8d94afafa8e55fd 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __I386_SGI_LITHIUM_H
-#define __I386_SGI_LITHIUM_H
+#ifndef ASM_X86__VISWS__LITHIUM_H
+#define ASM_X86__VISWS__LITHIUM_H
 
 #include <asm/fixmap.h>
 
@@ -49,5 +49,5 @@ static inline unsigned short li_pcib_read16(unsigned long reg)
        return *((volatile unsigned short *)(LI_PCIB_VADDR+reg));
 }
 
-#endif
+#endif /* ASM_X86__VISWS__LITHIUM_H */
 
index 83ea4f46e41984b2ecad1800a248dd3301675aae..61c938045ec95175dc74f81a9b414defb731bc03 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __I386_SGI_PIIX_H
-#define __I386_SGI_PIIX_H
+#ifndef ASM_X86__VISWS__PIIX4_H
+#define ASM_X86__VISWS__PIIX4_H
 
 /*
  * PIIX4 as used on SGI Visual Workstations
  */
 #define        PIIX_GPI_STPCLK         0x4     // STPCLK signal routed back in
 
-#endif
+#endif /* ASM_X86__VISWS__PIIX4_H */
index 5ce351325e011c72721d1f58c0b6e2d6f16f77e7..998bd18eb737d5911b8e3ffa62725957aae9a2d5 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _LINUX_VM86_H
-#define _LINUX_VM86_H
+#ifndef ASM_X86__VM86_H
+#define ASM_X86__VM86_H
 
 /*
  * I'm guessing at the VIF/VIP flag usage, but hope that this is how
@@ -205,4 +205,4 @@ static inline int handle_vm86_trap(struct kernel_vm86_regs *a, long b, int c)
 
 #endif /* __KERNEL__ */
 
-#endif
+#endif /* ASM_X86__VM86_H */
index c3118c3851565c9ae7a87e0d98e355fbf3efdc7a..b2d39e6a08b73a0aec01c226e2a78c2e9ed02652 100644 (file)
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef __VMI_TIME_H
-#define __VMI_TIME_H
+#ifndef ASM_X86__VMI_TIME_H
+#define ASM_X86__VMI_TIME_H
 
 /*
  * Raw VMI call indices for timer functions
@@ -95,4 +95,4 @@ extern void __devinit vmi_time_ap_init(void);
 
 #define CONFIG_VMI_ALARM_HZ    100
 
-#endif
+#endif /* ASM_X86__VMI_TIME_H */
index 6b66ff905af0408ee9ff586c4fe49dfc001c9af1..dcd4682413de06bb0c9e41126fbb4f6d8597b104 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_64_VSYSCALL_H_
-#define _ASM_X86_64_VSYSCALL_H_
+#ifndef ASM_X86__VSYSCALL_H
+#define ASM_X86__VSYSCALL_H
 
 enum vsyscall_num {
        __NR_vgettimeofday,
@@ -41,4 +41,4 @@ extern void map_vsyscall(void);
 
 #endif /* __KERNEL__ */
 
-#endif /* _ASM_X86_64_VSYSCALL_H_ */
+#endif /* ASM_X86__VSYSCALL_H */
index 8ded7472002419e1067a663799dff272623190d0..8151f5b8b6cb577588b15f8cb0ef9eb1f42da451 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __XEN_EVENTS_H
-#define __XEN_EVENTS_H
+#ifndef ASM_X86__XEN__EVENTS_H
+#define ASM_X86__XEN__EVENTS_H
 
 enum ipi_vector {
        XEN_RESCHEDULE_VECTOR,
@@ -21,4 +21,4 @@ static inline void xen_do_IRQ(int irq, struct pt_regs *regs)
        do_IRQ(regs);
 }
 
-#endif /* __XEN_EVENTS_H */
+#endif /* ASM_X86__XEN__EVENTS_H */
index 2444d4593a3babf29547dae15fc03fdd876f088c..c4baab4d2b68d9f94b10839f6941658f3923519d 100644 (file)
@@ -1,7 +1,7 @@
-#ifndef __XEN_GRANT_TABLE_H
-#define __XEN_GRANT_TABLE_H
+#ifndef ASM_X86__XEN__GRANT_TABLE_H
+#define ASM_X86__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 */
+#endif /* ASM_X86__XEN__GRANT_TABLE_H */
index 91cb7fd5c1234be0f549b44f8a93208c7fedd92d..44f4259bee3f0d72a9de91a90c6adfaf0bec6abf 100644 (file)
@@ -30,8 +30,8 @@
  * IN THE SOFTWARE.
  */
 
-#ifndef __HYPERCALL_H__
-#define __HYPERCALL_H__
+#ifndef ASM_X86__XEN__HYPERCALL_H
+#define ASM_X86__XEN__HYPERCALL_H
 
 #include <linux/errno.h>
 #include <linux/string.h>
@@ -524,4 +524,4 @@ MULTI_stack_switch(struct multicall_entry *mcl,
        mcl->args[1] = esp;
 }
 
-#endif /* __HYPERCALL_H__ */
+#endif /* ASM_X86__XEN__HYPERCALL_H */
index 8e15dd28c91fc18d116f34e0f69b030d444f3305..06c350452c500f48060f087cd0bd206fafb9a9b0 100644 (file)
@@ -30,8 +30,8 @@
  * IN THE SOFTWARE.
  */
 
-#ifndef __HYPERVISOR_H__
-#define __HYPERVISOR_H__
+#ifndef ASM_X86__XEN__HYPERVISOR_H
+#define ASM_X86__XEN__HYPERVISOR_H
 
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -70,4 +70,4 @@ u64 jiffies_to_st(unsigned long jiffies);
 
 #define is_running_on_xen()    (xen_start_info ? 1 : 0)
 
-#endif /* __HYPERVISOR_H__ */
+#endif /* ASM_X86__XEN__HYPERVISOR_H */
index 9d810f2538a2227083bbe8b6bc7a7b753c9add7b..d077bba96da9753d4db566f511575ea8fe0b23db 100644 (file)
@@ -6,8 +6,8 @@
  * Copyright (c) 2004, K A Fraser
  */
 
-#ifndef __ASM_X86_XEN_INTERFACE_H
-#define __ASM_X86_XEN_INTERFACE_H
+#ifndef ASM_X86__XEN__INTERFACE_H
+#define ASM_X86__XEN__INTERFACE_H
 
 #ifdef __XEN__
 #define __DEFINE_GUEST_HANDLE(name, type) \
@@ -172,4 +172,4 @@ DEFINE_GUEST_HANDLE_STRUCT(vcpu_guest_context);
 #define XEN_CPUID          XEN_EMULATE_PREFIX "cpuid"
 #endif
 
-#endif /* __ASM_X86_XEN_INTERFACE_H */
+#endif /* ASM_X86__XEN__INTERFACE_H */
index d8ac41d5db864cfb8ca560cde4efa23fcf823ea6..08167e19fc66cdefbdc3e50c3457750a8c324115 100644 (file)
@@ -6,8 +6,8 @@
  * Copyright (c) 2004, K A Fraser
  */
 
-#ifndef __ASM_X86_XEN_INTERFACE_32_H
-#define __ASM_X86_XEN_INTERFACE_32_H
+#ifndef ASM_X86__XEN__INTERFACE_32_H
+#define ASM_X86__XEN__INTERFACE_32_H
 
 
 /*
@@ -94,4 +94,4 @@ typedef struct xen_callback xen_callback_t;
 #define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
 #define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
 
-#endif /* __ASM_X86_XEN_INTERFACE_32_H */
+#endif /* ASM_X86__XEN__INTERFACE_32_H */
index 842266ce96e66d0c1ef2ca6aa9dacce59ce72b02..046c0f1e01d4095574ce63716f34f104bfc1d8fc 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_X86_XEN_INTERFACE_64_H
-#define __ASM_X86_XEN_INTERFACE_64_H
+#ifndef ASM_X86__XEN__INTERFACE_64_H
+#define ASM_X86__XEN__INTERFACE_64_H
 
 /*
  * 64-bit segment selectors
@@ -156,4 +156,4 @@ typedef unsigned long xen_callback_t;
 #endif /* !__ASSEMBLY__ */
 
 
-#endif /* __ASM_X86_XEN_INTERFACE_64_H */
+#endif /* ASM_X86__XEN__INTERFACE_64_H */
index 7b3835d3b77d9b910228fc0362b19747eb441e26..c50185dccec192bdef7e0d936863d5503cc304d5 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __XEN_PAGE_H
-#define __XEN_PAGE_H
+#ifndef ASM_X86__XEN__PAGE_H
+#define ASM_X86__XEN__PAGE_H
 
 #include <linux/pfn.h>
 
@@ -162,4 +162,4 @@ xmaddr_t arbitrary_virt_to_machine(void *address);
 void make_lowmem_page_readonly(void *vaddr);
 void make_lowmem_page_readwrite(void *vaddr);
 
-#endif /* __XEN_PAGE_H */
+#endif /* ASM_X86__XEN__PAGE_H */
index d12498ec8a4edc7deedd36f2d27a189f9cb197a0..ee48ef8fb2eafff29c8aefe67024709d7696e69d 100644 (file)
@@ -101,6 +101,24 @@ static inline int crypto_ahash_digest(struct ahash_request *req)
        return crt->digest(req);
 }
 
+static inline int crypto_ahash_init(struct ahash_request *req)
+{
+       struct ahash_tfm *crt = crypto_ahash_crt(crypto_ahash_reqtfm(req));
+       return crt->init(req);
+}
+
+static inline int crypto_ahash_update(struct ahash_request *req)
+{
+       struct ahash_tfm *crt = crypto_ahash_crt(crypto_ahash_reqtfm(req));
+       return crt->update(req);
+}
+
+static inline int crypto_ahash_final(struct ahash_request *req)
+{
+       struct ahash_tfm *crt = crypto_ahash_crt(crypto_ahash_reqtfm(req));
+       return crt->final(req);
+}
+
 static inline void ahash_request_set_tfm(struct ahash_request *req,
                                         struct crypto_ahash *tfm)
 {
index d2961b66d53dbab52a3f69cd30a441725c4000ee..57faa60de9bd48bef32a6acf9eeff9785b09e48f 100644 (file)
@@ -55,4 +55,49 @@ extern void complete_all(struct completion *);
 
 #define INIT_COMPLETION(x)     ((x).done = 0)
 
+
+/**
+ *     try_wait_for_completion - try to decrement a completion without blocking
+ *     @x:     completion structure
+ *
+ *     Returns: 0 if a decrement cannot be done without blocking
+ *              1 if a decrement succeeded.
+ *
+ *     If a completion is being used as a counting completion,
+ *     attempt to decrement the counter without blocking. This
+ *     enables us to avoid waiting if the resource the completion
+ *     is protecting is not available.
+ */
+static inline bool try_wait_for_completion(struct completion *x)
+{
+       int ret = 1;
+
+       spin_lock_irq(&x->wait.lock);
+       if (!x->done)
+               ret = 0;
+       else
+               x->done--;
+       spin_unlock_irq(&x->wait.lock);
+       return ret;
+}
+
+/**
+ *     completion_done - Test to see if a completion has any waiters
+ *     @x:     completion structure
+ *
+ *     Returns: 0 if there are waiters (wait_for_completion() in progress)
+ *              1 if there are no waiters.
+ *
+ */
+static inline bool completion_done(struct completion *x)
+{
+       int ret = 1;
+
+       spin_lock_irq(&x->wait.lock);
+       if (!x->done)
+               ret = 0;
+       spin_unlock_irq(&x->wait.lock);
+       return ret;
+}
+
 #endif
diff --git a/include/linux/cred.h b/include/linux/cred.h
new file mode 100644 (file)
index 0000000..b69222c
--- /dev/null
@@ -0,0 +1,50 @@
+/* Credentials management
+ *
+ * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_CRED_H
+#define _LINUX_CRED_H
+
+#define get_current_user()     (get_uid(current->user))
+
+#define task_uid(task)         ((task)->uid)
+#define task_gid(task)         ((task)->gid)
+#define task_euid(task)                ((task)->euid)
+#define task_egid(task)                ((task)->egid)
+
+#define current_uid()          (current->uid)
+#define current_gid()          (current->gid)
+#define current_euid()         (current->euid)
+#define current_egid()         (current->egid)
+#define current_suid()         (current->suid)
+#define current_sgid()         (current->sgid)
+#define current_fsuid()                (current->fsuid)
+#define current_fsgid()                (current->fsgid)
+#define current_cap()          (current->cap_effective)
+
+#define current_uid_gid(_uid, _gid)            \
+do {                                           \
+       *(_uid) = current->uid;                 \
+       *(_gid) = current->gid;                 \
+} while(0)
+
+#define current_euid_egid(_uid, _gid)          \
+do {                                           \
+       *(_uid) = current->euid;                \
+       *(_gid) = current->egid;                \
+} while(0)
+
+#define current_fsuid_fsgid(_uid, _gid)                \
+do {                                           \
+       *(_uid) = current->fsuid;               \
+       *(_gid) = current->fsgid;               \
+} while(0)
+
+#endif /* _LINUX_CRED_H */
index 56c73b8475519cc7ee5db5886c92aa6d8f5f2d15..c360c558e59eb5b58952955e3172658ed86f8848 100644 (file)
 #include <linux/types.h>
 #include <linux/msi.h>
 
-#ifdef CONFIG_DMAR
+#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
 struct intel_iommu;
 
+struct dmar_drhd_unit {
+       struct list_head list;          /* list of drhd units   */
+       struct  acpi_dmar_header *hdr;  /* ACPI header          */
+       u64     reg_base_addr;          /* register base address*/
+       struct  pci_dev **devices;      /* target device array  */
+       int     devices_cnt;            /* target device count  */
+       u8      ignored:1;              /* ignore drhd          */
+       u8      include_all:1;
+       struct intel_iommu *iommu;
+};
+
+extern struct list_head dmar_drhd_units;
+
+#define for_each_drhd_unit(drhd) \
+       list_for_each_entry(drhd, &dmar_drhd_units, list)
+
+extern int dmar_table_init(void);
+extern int early_dmar_detect(void);
+extern int dmar_dev_scope_init(void);
+
+/* Intel IOMMU detection */
+extern void detect_intel_iommu(void);
+
+
+extern int parse_ioapics_under_ir(void);
+extern int alloc_iommu(struct dmar_drhd_unit *);
+#else
+static inline void detect_intel_iommu(void)
+{
+       return;
+}
+
+static inline int dmar_table_init(void)
+{
+       return -ENODEV;
+}
+#endif /* !CONFIG_DMAR && !CONFIG_INTR_REMAP */
+
+#ifdef CONFIG_INTR_REMAP
+extern int intr_remapping_enabled;
+extern int enable_intr_remapping(int);
+
+struct irte {
+       union {
+               struct {
+                       __u64   present         : 1,
+                               fpd             : 1,
+                               dst_mode        : 1,
+                               redir_hint      : 1,
+                               trigger_mode    : 1,
+                               dlvry_mode      : 3,
+                               avail           : 4,
+                               __reserved_1    : 4,
+                               vector          : 8,
+                               __reserved_2    : 8,
+                               dest_id         : 32;
+               };
+               __u64 low;
+       };
+
+       union {
+               struct {
+                       __u64   sid             : 16,
+                               sq              : 2,
+                               svt             : 2,
+                               __reserved_3    : 44;
+               };
+               __u64 high;
+       };
+};
+extern int get_irte(int irq, struct irte *entry);
+extern int modify_irte(int irq, struct irte *irte_modified);
+extern int alloc_irte(struct intel_iommu *iommu, int irq, u16 count);
+extern int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index,
+                       u16 sub_handle);
+extern int map_irq_to_irte_handle(int irq, u16 *sub_handle);
+extern int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index);
+extern int flush_irte(int irq);
+extern int free_irte(int irq);
+
+extern int irq_remapped(int irq);
+extern struct intel_iommu *map_dev_to_ir(struct pci_dev *dev);
+extern struct intel_iommu *map_ioapic_to_ir(int apic);
+#else
+#define irq_remapped(irq)              (0)
+#define enable_intr_remapping(mode)    (-1)
+#define intr_remapping_enabled         (0)
+#endif
+
+#ifdef CONFIG_DMAR
 extern const char *dmar_get_fault_reason(u8 fault_reason);
 
 /* Can't use the common MSI interrupt functions
@@ -40,47 +130,30 @@ extern void dmar_msi_write(int irq, struct msi_msg *msg);
 extern int dmar_set_interrupt(struct intel_iommu *iommu);
 extern int arch_setup_dmar_msi(unsigned int irq);
 
-/* Intel IOMMU detection and initialization functions */
-extern void detect_intel_iommu(void);
-extern int intel_iommu_init(void);
-
-extern int dmar_table_init(void);
-extern int early_dmar_detect(void);
-
-extern struct list_head dmar_drhd_units;
+extern int iommu_detected, no_iommu;
 extern struct list_head dmar_rmrr_units;
-
-struct dmar_drhd_unit {
-       struct list_head list;          /* list of drhd units   */
-       u64     reg_base_addr;          /* register base address*/
-       struct  pci_dev **devices;      /* target device array  */
-       int     devices_cnt;            /* target device count  */
-       u8      ignored:1;              /* ignore drhd          */
-       u8      include_all:1;
-       struct intel_iommu *iommu;
-};
-
 struct dmar_rmrr_unit {
        struct list_head list;          /* list of rmrr units   */
+       struct acpi_dmar_header *hdr;   /* ACPI header          */
        u64     base_address;           /* reserved base address*/
        u64     end_address;            /* reserved end address */
        struct pci_dev **devices;       /* target devices */
        int     devices_cnt;            /* target device count */
 };
 
-#define for_each_drhd_unit(drhd) \
-       list_for_each_entry(drhd, &dmar_drhd_units, list)
 #define for_each_rmrr_units(rmrr) \
        list_for_each_entry(rmrr, &dmar_rmrr_units, list)
+/* Intel DMAR  initialization functions */
+extern int intel_iommu_init(void);
+extern int dmar_disabled;
 #else
-static inline void detect_intel_iommu(void)
-{
-       return;
-}
 static inline int intel_iommu_init(void)
 {
+#ifdef CONFIG_INTR_REMAP
+       return dmar_dev_scope_init();
+#else
        return -ENODEV;
+#endif
 }
-
 #endif /* !CONFIG_DMAR */
 #endif /* __DMAR_H__ */
index 8ccb462ea42c4cb3c4813c51ad285fb168efc2f9..8d9411bc60f6f9356e0237cc601330576283d22a 100644 (file)
@@ -62,6 +62,7 @@ typedef       void (*irq_flow_handler_t)(unsigned int irq,
 #define IRQ_MOVE_PENDING       0x00200000      /* need to re-target IRQ destination */
 #define IRQ_NO_BALANCING       0x00400000      /* IRQ is excluded from balancing */
 #define IRQ_SPURIOUS_DISABLED  0x00800000      /* IRQ was disabled by the spurious trap */
+#define IRQ_MOVE_PCNTXT        0x01000000      /* IRQ migration from process context */
 
 #ifdef CONFIG_IRQ_PER_CPU
 # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
index 5850bfb968a87079d767387169a0847e8530f217..cfb0d87b99fcafb8ff0eb753e0ea489dc20478dd 100644 (file)
@@ -87,6 +87,7 @@ struct sched_param {
 #include <linux/task_io_accounting.h>
 #include <linux/kobject.h>
 #include <linux/latencytop.h>
+#include <linux/cred.h>
 
 #include <asm/processor.h>
 
index cfcc45b3bef0e7a1f1c582786aed7fc1d7bfdafc..358661c9990e85a0b3c523a72606ee86411c1b57 100644 (file)
@@ -901,7 +901,7 @@ extern unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta);
 static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len)
 {
        if (len > skb_headlen(skb) &&
-           !__pskb_pull_tail(skb, len-skb_headlen(skb)))
+           !__pskb_pull_tail(skb, len - skb_headlen(skb)))
                return NULL;
        skb->len -= len;
        return skb->data += len;
@@ -918,7 +918,7 @@ static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
                return 1;
        if (unlikely(len > skb->len))
                return 0;
-       return __pskb_pull_tail(skb, len-skb_headlen(skb)) != NULL;
+       return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL;
 }
 
 /**
@@ -1321,7 +1321,7 @@ static inline int skb_padto(struct sk_buff *skb, unsigned int len)
        unsigned int size = skb->len;
        if (likely(size >= len))
                return 0;
-       return skb_pad(skb, len-size);
+       return skb_pad(skb, len - size);
 }
 
 static inline int skb_add_data(struct sk_buff *skb,
index 5811c5da69f938275e4ba595a23fc252b4c0fc1a..0924cd9c30f66feae597186d2b08d67155f008ad 100644 (file)
@@ -110,6 +110,8 @@ enum usb_interface_condition {
  * @sysfs_files_created: sysfs attributes exist
  * @needs_remote_wakeup: flag set when the driver requires remote-wakeup
  *     capability during autosuspend.
+ * @needs_binding: flag set when the driver should be re-probed or unbound
+ *     following a reset or suspend operation it doesn't support.
  * @dev: driver model's view of this device
  * @usb_dev: if an interface is bound to the USB major, this will point
  *     to the sysfs representation for that device.
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
new file mode 100644 (file)
index 0000000..630962c
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * This is used to for host and peripheral modes of the driver for
+ * Inventra (Multidrop) Highspeed Dual-Role Controllers:  (M)HDRC.
+ *
+ * Board initialization should put one of these into dev->platform_data,
+ * probably on some platform_device named "musb_hdrc".  It encapsulates
+ * key configuration differences between boards.
+ */
+
+/* The USB role is defined by the connector used on the board, so long as
+ * standards are being followed.  (Developer boards sometimes won't.)
+ */
+enum musb_mode {
+       MUSB_UNDEFINED = 0,
+       MUSB_HOST,              /* A or Mini-A connector */
+       MUSB_PERIPHERAL,        /* B or Mini-B connector */
+       MUSB_OTG                /* Mini-AB connector */
+};
+
+struct clk;
+
+struct musb_hdrc_eps_bits {
+       const char      name[16];
+       u8              bits;
+};
+
+struct musb_hdrc_config {
+       /* MUSB configuration-specific details */
+       unsigned        multipoint:1;   /* multipoint device */
+       unsigned        dyn_fifo:1;     /* supports dynamic fifo sizing */
+       unsigned        soft_con:1;     /* soft connect required */
+       unsigned        utm_16:1;       /* utm data witdh is 16 bits */
+       unsigned        big_endian:1;   /* true if CPU uses big-endian */
+       unsigned        mult_bulk_tx:1; /* Tx ep required for multbulk pkts */
+       unsigned        mult_bulk_rx:1; /* Rx ep required for multbulk pkts */
+       unsigned        high_iso_tx:1;  /* Tx ep required for HB iso */
+       unsigned        high_iso_rx:1;  /* Rx ep required for HD iso */
+       unsigned        dma:1;          /* supports DMA */
+       unsigned        vendor_req:1;   /* vendor registers required */
+
+       u8              num_eps;        /* number of endpoints _with_ ep0 */
+       u8              dma_channels;   /* number of dma channels */
+       u8              dyn_fifo_size;  /* dynamic size in bytes */
+       u8              vendor_ctrl;    /* vendor control reg width */
+       u8              vendor_stat;    /* vendor status reg witdh */
+       u8              dma_req_chan;   /* bitmask for required dma channels */
+       u8              ram_bits;       /* ram address size */
+
+       struct musb_hdrc_eps_bits *eps_bits;
+};
+
+struct musb_hdrc_platform_data {
+       /* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */
+       u8              mode;
+
+       /* for clk_get() */
+       const char      *clock;
+
+       /* (HOST or OTG) switch VBUS on/off */
+       int             (*set_vbus)(struct device *dev, int is_on);
+
+       /* (HOST or OTG) mA/2 power supplied on (default = 8mA) */
+       u8              power;
+
+       /* (PERIPHERAL) mA/2 max power consumed (default = 100mA) */
+       u8              min_power;
+
+       /* (HOST or OTG) msec/2 after VBUS on till power good */
+       u8              potpgt;
+
+       /* Power the device on or off */
+       int             (*set_power)(int state);
+
+       /* Turn device clock on or off */
+       int             (*set_clock)(struct clk *clock, int is_on);
+
+       /* MUSB configuration-specific details */
+       struct musb_hdrc_config *config;
+};
+
+
+/* TUSB 6010 support */
+
+#define        TUSB6010_OSCCLK_60      16667   /* psec/clk @ 60.0 MHz */
+#define        TUSB6010_REFCLK_24      41667   /* psec/clk @ 24.0 MHz XI */
+#define        TUSB6010_REFCLK_19      52083   /* psec/clk @ 19.2 MHz CLKIN */
+
+#ifdef CONFIG_ARCH_OMAP2
+
+extern int __init tusb6010_setup_interface(
+               struct musb_hdrc_platform_data *data,
+               unsigned ps_refclk, unsigned waitpin,
+               unsigned async_cs, unsigned sync_cs,
+               unsigned irq, unsigned dmachan);
+
+extern int tusb6010_platform_retime(unsigned is_refclk);
+
+#endif /* OMAP2 */
index 09a3e6a7518fc2e043fd3568f95b74d822b78af6..655341d0f534a370f7966aa617b8733b52124acb 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/mutex.h>
 
 #define SERIAL_TTY_MAJOR       188     /* Nice legal number now */
-#define SERIAL_TTY_MINORS      255     /* loads of devices :) */
+#define SERIAL_TTY_MINORS      254     /* loads of devices :) */
+#define SERIAL_TTY_NO_MINOR    255     /* No minor was assigned */
 
 /* The maximum number of ports one device can grab at once */
 #define MAX_NUM_PORTS          8
index 2f8b3c06a10198b7c51d1029965284c802a395b9..bc391ba101e9aa96996236c55584ebc67fbd86b9 100644 (file)
@@ -38,11 +38,6 @@ struct route_info {
 #define RT6_LOOKUP_F_SRCPREF_COA       0x00000020
 
 
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-extern struct rt6_info *ip6_prohibit_entry;
-extern struct rt6_info *ip6_blk_hole_entry;
-#endif
-
 extern void                    ip6_route_input(struct sk_buff *skb);
 
 extern struct dst_entry *      ip6_route_output(struct net *net,
@@ -118,7 +113,6 @@ extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
 extern void rt6_ifdown(struct net *net, struct net_device *dev);
 extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
 
-extern rwlock_t rt6_lock;
 
 /*
  *     Store a destination cache entry in a socket
index cbb59ebed4aebaf7003d3db98b061e7b07b5d9f7..7312c3dd309f2cc705a678f29be79a972780f2ec 100644 (file)
@@ -140,8 +140,24 @@ struct ip_vs_seq {
 
 
 /*
- *     IPVS statistics object
+ *     IPVS statistics objects
  */
+struct ip_vs_estimator {
+       struct list_head        list;
+
+       u64                     last_inbytes;
+       u64                     last_outbytes;
+       u32                     last_conns;
+       u32                     last_inpkts;
+       u32                     last_outpkts;
+
+       u32                     cps;
+       u32                     inpps;
+       u32                     outpps;
+       u32                     inbps;
+       u32                     outbps;
+};
+
 struct ip_vs_stats
 {
        __u32                   conns;          /* connections scheduled */
@@ -156,7 +172,15 @@ struct ip_vs_stats
        __u32                   inbps;          /* current in byte rate */
        __u32                   outbps;         /* current out byte rate */
 
+       /*
+        * Don't add anything before the lock, because we use memcpy() to copy
+        * the members before the lock to struct ip_vs_stats_user in
+        * ip_vs_ctl.c.
+        */
+
        spinlock_t              lock;           /* spin lock */
+
+       struct ip_vs_estimator  est;            /* estimator */
 };
 
 struct dst_entry;
@@ -440,7 +464,7 @@ struct ip_vs_app
  */
 extern const char *ip_vs_proto_name(unsigned proto);
 extern void ip_vs_init_hash_table(struct list_head *table, int rows);
-#define IP_VS_INIT_HASH_TABLE(t) ip_vs_init_hash_table(t, sizeof(t)/sizeof(t[0]))
+#define IP_VS_INIT_HASH_TABLE(t) ip_vs_init_hash_table((t), ARRAY_SIZE((t)))
 
 #define IP_VS_APP_TYPE_FTP     1
 
@@ -620,7 +644,7 @@ extern int sysctl_ip_vs_expire_quiescent_template;
 extern int sysctl_ip_vs_sync_threshold[2];
 extern int sysctl_ip_vs_nat_icmp_send;
 extern struct ip_vs_stats ip_vs_stats;
-extern struct ctl_path net_vs_ctl_path[];
+extern const struct ctl_path net_vs_ctl_path[];
 
 extern struct ip_vs_service *
 ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport);
@@ -659,7 +683,7 @@ extern void ip_vs_sync_conn(struct ip_vs_conn *cp);
 /*
  *      IPVS rate estimator prototypes (from ip_vs_est.c)
  */
-extern int ip_vs_new_estimator(struct ip_vs_stats *stats);
+extern void ip_vs_new_estimator(struct ip_vs_stats *stats);
 extern void ip_vs_kill_estimator(struct ip_vs_stats *stats);
 extern void ip_vs_zero_estimator(struct ip_vs_stats *stats);
 
index 6affcfaa123edda5df7f65275d117063ed00018d..853fe83d9f3700b9179e8a82c794970411ac5c20 100644 (file)
@@ -89,7 +89,10 @@ extern void __qdisc_run(struct Qdisc *q);
 
 static inline void qdisc_run(struct Qdisc *q)
 {
-       if (!test_and_set_bit(__QDISC_STATE_RUNNING, &q->state))
+       struct netdev_queue *txq = q->dev_queue;
+
+       if (!netif_tx_queue_stopped(txq) &&
+           !test_and_set_bit(__QDISC_STATE_RUNNING, &q->state))
                __qdisc_run(q);
 }
 
index 0314074fa232e72370db9e62b50cdc98a8d53f6a..60c49e324390bca07f9109fc2bb09d0ecf18f5c6 100644 (file)
@@ -89,7 +89,14 @@ int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
        set_balance_irq_affinity(irq, cpumask);
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
-       set_pending_irq(irq, cpumask);
+       if (desc->status & IRQ_MOVE_PCNTXT) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&desc->lock, flags);
+               desc->chip->set_affinity(irq, cpumask);
+               spin_unlock_irqrestore(&desc->lock, flags);
+       } else
+               set_pending_irq(irq, cpumask);
 #else
        desc->affinity = cpumask;
        desc->chip->set_affinity(irq, cpumask);
index 57abe8266be198dd483c71ce07cf3ce0757ced0e..a89f32fa94f6b0f9631a7353f3cbfd2e68bdcb70 100644 (file)
@@ -99,7 +99,7 @@ struct gen_estimator_head
 
 static struct gen_estimator_head elist[EST_MAX_INTERVAL+1];
 
-/* Protects against NULL dereference */
+/* Protects against NULL dereference and RCU write-side */
 static DEFINE_RWLOCK(est_lock);
 
 static void est_timer(unsigned long arg)
@@ -185,6 +185,7 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
        est->last_packets = bstats->packets;
        est->avpps = rate_est->pps<<10;
 
+       write_lock_bh(&est_lock);
        if (!elist[idx].timer.function) {
                INIT_LIST_HEAD(&elist[idx].list);
                setup_timer(&elist[idx].timer, est_timer, idx);
@@ -194,6 +195,7 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
                mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx));
 
        list_add_rcu(&est->list, &elist[idx].list);
+       write_unlock_bh(&est_lock);
        return 0;
 }
 
@@ -212,7 +214,6 @@ static void __gen_kill_estimator(struct rcu_head *head)
  * Removes the rate estimator specified by &bstats and &rate_est
  * and deletes the timer.
  *
- * NOTE: Called under rtnl_mutex
  */
 void gen_kill_estimator(struct gnet_stats_basic *bstats,
        struct gnet_stats_rate_est *rate_est)
@@ -226,17 +227,17 @@ void gen_kill_estimator(struct gnet_stats_basic *bstats,
                if (!elist[idx].timer.function)
                        continue;
 
+               write_lock_bh(&est_lock);
                list_for_each_entry_safe(e, n, &elist[idx].list, list) {
                        if (e->rate_est != rate_est || e->bstats != bstats)
                                continue;
 
-                       write_lock_bh(&est_lock);
                        e->bstats = NULL;
-                       write_unlock_bh(&est_lock);
 
                        list_del_rcu(&e->list);
                        call_rcu(&e->e_rcu, __gen_kill_estimator);
                }
+               write_unlock_bh(&est_lock);
        }
 }
 
index 526236453908280654104886d09e26e0117aba80..a756847e3814e5fc9e425f105acfd2984eccb33a 100644 (file)
@@ -1961,6 +1961,8 @@ static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname)
  */
 static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
 {
+       int ntxq;
+
        if (!pkt_dev->odev) {
                printk(KERN_ERR "pktgen: ERROR: pkt_dev->odev == NULL in "
                       "setup_inject.\n");
@@ -1969,6 +1971,33 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
                return;
        }
 
+       /* make sure that we don't pick a non-existing transmit queue */
+       ntxq = pkt_dev->odev->real_num_tx_queues;
+       if (ntxq <= num_online_cpus() && (pkt_dev->flags & F_QUEUE_MAP_CPU)) {
+               printk(KERN_WARNING "pktgen: WARNING: QUEUE_MAP_CPU "
+                      "disabled because CPU count (%d) exceeds number ",
+                      num_online_cpus());
+               printk(KERN_WARNING "pktgen: WARNING: of tx queues "
+                      "(%d) on %s \n", ntxq, pkt_dev->odev->name);
+               pkt_dev->flags &= ~F_QUEUE_MAP_CPU;
+       }
+       if (ntxq <= pkt_dev->queue_map_min) {
+               printk(KERN_WARNING "pktgen: WARNING: Requested "
+                      "queue_map_min (%d) exceeds number of tx\n",
+                      pkt_dev->queue_map_min);
+               printk(KERN_WARNING "pktgen: WARNING: queues (%d) on "
+                      "%s, resetting\n", ntxq, pkt_dev->odev->name);
+               pkt_dev->queue_map_min = ntxq - 1;
+       }
+       if (ntxq <= pkt_dev->queue_map_max) {
+               printk(KERN_WARNING "pktgen: WARNING: Requested "
+                      "queue_map_max (%d) exceeds number of tx\n",
+                      pkt_dev->queue_map_max);
+               printk(KERN_WARNING "pktgen: WARNING: queues (%d) on "
+                      "%s, resetting\n", ntxq, pkt_dev->odev->name);
+               pkt_dev->queue_map_max = ntxq - 1;
+       }
+
        /* Default to the interface's mac if not explicitly set. */
 
        if (is_zero_ether_addr(pkt_dev->src_mac))
index b622d9744856a9e8320f812cb9e9d85699f1a6a0..1ca3b26eed0fb09c479d4e513efd2d185c69bcc0 100644 (file)
@@ -474,6 +474,11 @@ static int dccp_setsockopt_change(struct sock *sk, int type,
 
        if (copy_from_user(&opt, optval, sizeof(opt)))
                return -EFAULT;
+       /*
+        * rfc4340: 6.1. Change Options
+        */
+       if (opt.dccpsf_len < 1)
+               return -EINVAL;
 
        val = kmalloc(opt.dccpsf_len, GFP_KERNEL);
        if (!val)
index 6203ece53606e63e0b36f0b377ed84794f474ef5..f70fac612596168981f85e052790b53fa4743836 100644 (file)
@@ -289,6 +289,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
        struct rtable *rt;
        struct iphdr *pip;
        struct igmpv3_report *pig;
+       struct net *net = dev_net(dev);
 
        skb = alloc_skb(size + LL_ALLOCATED_SPACE(dev), GFP_ATOMIC);
        if (skb == NULL)
@@ -299,7 +300,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
                                    .nl_u = { .ip4_u = {
                                    .daddr = IGMPV3_ALL_MCR } },
                                    .proto = IPPROTO_IGMP };
-               if (ip_route_output_key(&init_net, &rt, &fl)) {
+               if (ip_route_output_key(net, &rt, &fl)) {
                        kfree_skb(skb);
                        return NULL;
                }
@@ -629,6 +630,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
        struct igmphdr *ih;
        struct rtable *rt;
        struct net_device *dev = in_dev->dev;
+       struct net *net = dev_net(dev);
        __be32  group = pmc ? pmc->multiaddr : 0;
        __be32  dst;
 
@@ -643,7 +645,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
                struct flowi fl = { .oif = dev->ifindex,
                                    .nl_u = { .ip4_u = { .daddr = dst } },
                                    .proto = IPPROTO_IGMP };
-               if (ip_route_output_key(&init_net, &rt, &fl))
+               if (ip_route_output_key(net, &rt, &fl))
                        return -1;
        }
        if (rt->rt_src == 0) {
@@ -1196,9 +1198,6 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
 
        ASSERT_RTNL();
 
-       if (!net_eq(dev_net(in_dev->dev), &init_net))
-               return;
-
        for (im=in_dev->mc_list; im; im=im->next) {
                if (im->multiaddr == addr) {
                        im->users++;
@@ -1278,9 +1277,6 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
 
        ASSERT_RTNL();
 
-       if (!net_eq(dev_net(in_dev->dev), &init_net))
-               return;
-
        for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) {
                if (i->multiaddr==addr) {
                        if (--i->users == 0) {
@@ -1308,9 +1304,6 @@ void ip_mc_down(struct in_device *in_dev)
 
        ASSERT_RTNL();
 
-       if (!net_eq(dev_net(in_dev->dev), &init_net))
-               return;
-
        for (i=in_dev->mc_list; i; i=i->next)
                igmp_group_dropped(i);
 
@@ -1331,9 +1324,6 @@ void ip_mc_init_dev(struct in_device *in_dev)
 {
        ASSERT_RTNL();
 
-       if (!net_eq(dev_net(in_dev->dev), &init_net))
-               return;
-
        in_dev->mc_tomb = NULL;
 #ifdef CONFIG_IP_MULTICAST
        in_dev->mr_gq_running = 0;
@@ -1357,9 +1347,6 @@ void ip_mc_up(struct in_device *in_dev)
 
        ASSERT_RTNL();
 
-       if (!net_eq(dev_net(in_dev->dev), &init_net))
-               return;
-
        ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);
 
        for (i=in_dev->mc_list; i; i=i->next)
@@ -1376,9 +1363,6 @@ void ip_mc_destroy_dev(struct in_device *in_dev)
 
        ASSERT_RTNL();
 
-       if (!net_eq(dev_net(in_dev->dev), &init_net))
-               return;
-
        /* Deactivate timers */
        ip_mc_down(in_dev);
 
@@ -1395,7 +1379,7 @@ void ip_mc_destroy_dev(struct in_device *in_dev)
        write_unlock_bh(&in_dev->mc_list_lock);
 }
 
-static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
+static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
 {
        struct flowi fl = { .nl_u = { .ip4_u =
                                      { .daddr = imr->imr_multiaddr.s_addr } } };
@@ -1404,19 +1388,19 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
        struct in_device *idev = NULL;
 
        if (imr->imr_ifindex) {
-               idev = inetdev_by_index(&init_net, imr->imr_ifindex);
+               idev = inetdev_by_index(net, imr->imr_ifindex);
                if (idev)
                        __in_dev_put(idev);
                return idev;
        }
        if (imr->imr_address.s_addr) {
-               dev = ip_dev_find(&init_net, imr->imr_address.s_addr);
+               dev = ip_dev_find(net, imr->imr_address.s_addr);
                if (!dev)
                        return NULL;
                dev_put(dev);
        }
 
-       if (!dev && !ip_route_output_key(&init_net, &rt, &fl)) {
+       if (!dev && !ip_route_output_key(net, &rt, &fl)) {
                dev = rt->u.dst.dev;
                ip_rt_put(rt);
        }
@@ -1754,18 +1738,16 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
        struct ip_mc_socklist *iml=NULL, *i;
        struct in_device *in_dev;
        struct inet_sock *inet = inet_sk(sk);
+       struct net *net = sock_net(sk);
        int ifindex;
        int count = 0;
 
        if (!ipv4_is_multicast(addr))
                return -EINVAL;
 
-       if (!net_eq(sock_net(sk), &init_net))
-               return -EPROTONOSUPPORT;
-
        rtnl_lock();
 
-       in_dev = ip_mc_find_dev(imr);
+       in_dev = ip_mc_find_dev(net, imr);
 
        if (!in_dev) {
                iml = NULL;
@@ -1827,15 +1809,13 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
        struct inet_sock *inet = inet_sk(sk);
        struct ip_mc_socklist *iml, **imlp;
        struct in_device *in_dev;
+       struct net *net = sock_net(sk);
        __be32 group = imr->imr_multiaddr.s_addr;
        u32 ifindex;
        int ret = -EADDRNOTAVAIL;
 
-       if (!net_eq(sock_net(sk), &init_net))
-               return -EPROTONOSUPPORT;
-
        rtnl_lock();
-       in_dev = ip_mc_find_dev(imr);
+       in_dev = ip_mc_find_dev(net, imr);
        ifindex = imr->imr_ifindex;
        for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) {
                if (iml->multi.imr_multiaddr.s_addr != group)
@@ -1873,21 +1853,19 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
        struct in_device *in_dev = NULL;
        struct inet_sock *inet = inet_sk(sk);
        struct ip_sf_socklist *psl;
+       struct net *net = sock_net(sk);
        int leavegroup = 0;
        int i, j, rv;
 
        if (!ipv4_is_multicast(addr))
                return -EINVAL;
 
-       if (!net_eq(sock_net(sk), &init_net))
-               return -EPROTONOSUPPORT;
-
        rtnl_lock();
 
        imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr;
        imr.imr_address.s_addr = mreqs->imr_interface;
        imr.imr_ifindex = ifindex;
-       in_dev = ip_mc_find_dev(&imr);
+       in_dev = ip_mc_find_dev(net, &imr);
 
        if (!in_dev) {
                err = -ENODEV;
@@ -2007,6 +1985,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
        struct in_device *in_dev;
        struct inet_sock *inet = inet_sk(sk);
        struct ip_sf_socklist *newpsl, *psl;
+       struct net *net = sock_net(sk);
        int leavegroup = 0;
 
        if (!ipv4_is_multicast(addr))
@@ -2015,15 +1994,12 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
            msf->imsf_fmode != MCAST_EXCLUDE)
                return -EINVAL;
 
-       if (!net_eq(sock_net(sk), &init_net))
-               return -EPROTONOSUPPORT;
-
        rtnl_lock();
 
        imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
        imr.imr_address.s_addr = msf->imsf_interface;
        imr.imr_ifindex = ifindex;
-       in_dev = ip_mc_find_dev(&imr);
+       in_dev = ip_mc_find_dev(net, &imr);
 
        if (!in_dev) {
                err = -ENODEV;
@@ -2094,19 +2070,17 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
        struct in_device *in_dev;
        struct inet_sock *inet = inet_sk(sk);
        struct ip_sf_socklist *psl;
+       struct net *net = sock_net(sk);
 
        if (!ipv4_is_multicast(addr))
                return -EINVAL;
 
-       if (!net_eq(sock_net(sk), &init_net))
-               return -EPROTONOSUPPORT;
-
        rtnl_lock();
 
        imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
        imr.imr_address.s_addr = msf->imsf_interface;
        imr.imr_ifindex = 0;
-       in_dev = ip_mc_find_dev(&imr);
+       in_dev = ip_mc_find_dev(net, &imr);
 
        if (!in_dev) {
                err = -ENODEV;
@@ -2163,9 +2137,6 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
        if (!ipv4_is_multicast(addr))
                return -EINVAL;
 
-       if (!net_eq(sock_net(sk), &init_net))
-               return -EPROTONOSUPPORT;
-
        rtnl_lock();
 
        err = -EADDRNOTAVAIL;
@@ -2246,19 +2217,17 @@ void ip_mc_drop_socket(struct sock *sk)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct ip_mc_socklist *iml;
+       struct net *net = sock_net(sk);
 
        if (inet->mc_list == NULL)
                return;
 
-       if (!net_eq(sock_net(sk), &init_net))
-               return;
-
        rtnl_lock();
        while ((iml = inet->mc_list) != NULL) {
                struct in_device *in_dev;
                inet->mc_list = iml->next;
 
-               in_dev = inetdev_by_index(&init_net, iml->multi.imr_ifindex);
+               in_dev = inetdev_by_index(net, iml->multi.imr_ifindex);
                (void) ip_mc_leave_src(sk, iml, in_dev);
                if (in_dev != NULL) {
                        ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
index 1f1897a1a702d58069dc4d3de49c5845b9913eb0..201b8ea3020dbe4e55edb7c089c0b4bc7c5f0a79 100644 (file)
@@ -608,7 +608,7 @@ int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri,
 }
 
 
-int ip_vs_app_init(void)
+int __init ip_vs_app_init(void)
 {
        /* we will replace it with proc_net_ipvs_create() soon */
        proc_net_fops_create(&init_net, "ip_vs_app", 0, &ip_vs_app_fops);
index f8bdae47a77f6c32aff5e4af482e4334b2b0724e..44a6872dc24581b97f0338368aabb0c174fb5e0e 100644 (file)
@@ -965,7 +965,7 @@ static void ip_vs_conn_flush(void)
 }
 
 
-int ip_vs_conn_init(void)
+int __init ip_vs_conn_init(void)
 {
        int idx;
 
index 9a5ace0b4dd626f20d5cf4f72d8c08c50e69dcf5..6379705a8dcb2a98505af97ee4fa0f23045d61f8 100644 (file)
@@ -683,9 +683,22 @@ static void
 ip_vs_zero_stats(struct ip_vs_stats *stats)
 {
        spin_lock_bh(&stats->lock);
-       memset(stats, 0, (char *)&stats->lock - (char *)stats);
-       spin_unlock_bh(&stats->lock);
+
+       stats->conns = 0;
+       stats->inpkts = 0;
+       stats->outpkts = 0;
+       stats->inbytes = 0;
+       stats->outbytes = 0;
+
+       stats->cps = 0;
+       stats->inpps = 0;
+       stats->outpps = 0;
+       stats->inbps = 0;
+       stats->outbps = 0;
+
        ip_vs_zero_estimator(stats);
+
+       spin_unlock_bh(&stats->lock);
 }
 
 /*
@@ -1589,7 +1602,7 @@ static struct ctl_table vs_vars[] = {
        { .ctl_name = 0 }
 };
 
-struct ctl_path net_vs_ctl_path[] = {
+const struct ctl_path net_vs_ctl_path[] = {
        { .procname = "net", .ctl_name = CTL_NET, },
        { .procname = "ipv4", .ctl_name = NET_IPV4, },
        { .procname = "vs", },
@@ -1784,7 +1797,9 @@ static const struct file_operations ip_vs_info_fops = {
 
 #endif
 
-struct ip_vs_stats ip_vs_stats;
+struct ip_vs_stats ip_vs_stats = {
+       .lock = __SPIN_LOCK_UNLOCKED(ip_vs_stats.lock),
+};
 
 #ifdef CONFIG_PROC_FS
 static int ip_vs_stats_show(struct seq_file *seq, void *v)
@@ -2306,7 +2321,7 @@ static struct nf_sockopt_ops ip_vs_sockopts = {
 };
 
 
-int ip_vs_control_init(void)
+int __init ip_vs_control_init(void)
 {
        int ret;
        int idx;
@@ -2333,8 +2348,6 @@ int ip_vs_control_init(void)
                INIT_LIST_HEAD(&ip_vs_rtable[idx]);
        }
 
-       memset(&ip_vs_stats, 0, sizeof(ip_vs_stats));
-       spin_lock_init(&ip_vs_stats.lock);
        ip_vs_new_estimator(&ip_vs_stats);
 
        /* Hook the defense timer */
index 8afc1503ed20d05371cede9e0b3d5c0997549388..fa66824d264f6b21c84105cc00c3cb0c01e57534 100644 (file)
@@ -233,6 +233,7 @@ static struct ip_vs_scheduler ip_vs_dh_scheduler =
        .name =                 "dh",
        .refcnt =               ATOMIC_INIT(0),
        .module =               THIS_MODULE,
+       .n_list =               LIST_HEAD_INIT(ip_vs_dh_scheduler.n_list),
        .init_service =         ip_vs_dh_init_svc,
        .done_service =         ip_vs_dh_done_svc,
        .update_service =       ip_vs_dh_update_svc,
@@ -242,7 +243,6 @@ static struct ip_vs_scheduler ip_vs_dh_scheduler =
 
 static int __init ip_vs_dh_init(void)
 {
-       INIT_LIST_HEAD(&ip_vs_dh_scheduler.n_list);
        return register_ip_vs_scheduler(&ip_vs_dh_scheduler);
 }
 
index bc04eedd6dbb45b26853f3c39e9323c9a41900c4..5a20f93bd7f94033e59e6cefc25c072208c2b699 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
+#include <linux/list.h>
 
 #include <net/ip_vs.h>
 
  */
 
 
-struct ip_vs_estimator
-{
-       struct ip_vs_estimator  *next;
-       struct ip_vs_stats      *stats;
-
-       u32                     last_conns;
-       u32                     last_inpkts;
-       u32                     last_outpkts;
-       u64                     last_inbytes;
-       u64                     last_outbytes;
-
-       u32                     cps;
-       u32                     inpps;
-       u32                     outpps;
-       u32                     inbps;
-       u32                     outbps;
-};
-
+static void estimation_timer(unsigned long arg);
 
-static struct ip_vs_estimator *est_list = NULL;
-static DEFINE_RWLOCK(est_lock);
-static struct timer_list est_timer;
+static LIST_HEAD(est_list);
+static DEFINE_SPINLOCK(est_lock);
+static DEFINE_TIMER(est_timer, estimation_timer, 0, 0);
 
 static void estimation_timer(unsigned long arg)
 {
@@ -76,9 +60,9 @@ static void estimation_timer(unsigned long arg)
        u64 n_inbytes, n_outbytes;
        u32 rate;
 
-       read_lock(&est_lock);
-       for (e = est_list; e; e = e->next) {
-               s = e->stats;
+       spin_lock(&est_lock);
+       list_for_each_entry(e, &est_list, list) {
+               s = container_of(e, struct ip_vs_stats, est);
 
                spin_lock(&s->lock);
                n_conns = s->conns;
@@ -114,19 +98,16 @@ static void estimation_timer(unsigned long arg)
                s->outbps = (e->outbps+0xF)>>5;
                spin_unlock(&s->lock);
        }
-       read_unlock(&est_lock);
+       spin_unlock(&est_lock);
        mod_timer(&est_timer, jiffies + 2*HZ);
 }
 
-int ip_vs_new_estimator(struct ip_vs_stats *stats)
+void ip_vs_new_estimator(struct ip_vs_stats *stats)
 {
-       struct ip_vs_estimator *est;
+       struct ip_vs_estimator *est = &stats->est;
 
-       est = kzalloc(sizeof(*est), GFP_KERNEL);
-       if (est == NULL)
-               return -ENOMEM;
+       INIT_LIST_HEAD(&est->list);
 
-       est->stats = stats;
        est->last_conns = stats->conns;
        est->cps = stats->cps<<10;
 
@@ -142,59 +123,40 @@ int ip_vs_new_estimator(struct ip_vs_stats *stats)
        est->last_outbytes = stats->outbytes;
        est->outbps = stats->outbps<<5;
 
-       write_lock_bh(&est_lock);
-       est->next = est_list;
-       if (est->next == NULL) {
-               setup_timer(&est_timer, estimation_timer, 0);
-               est_timer.expires = jiffies + 2*HZ;
-               add_timer(&est_timer);
-       }
-       est_list = est;
-       write_unlock_bh(&est_lock);
-       return 0;
+       spin_lock_bh(&est_lock);
+       if (list_empty(&est_list))
+               mod_timer(&est_timer, jiffies + 2 * HZ);
+       list_add(&est->list, &est_list);
+       spin_unlock_bh(&est_lock);
 }
 
 void ip_vs_kill_estimator(struct ip_vs_stats *stats)
 {
-       struct ip_vs_estimator *est, **pest;
-       int killed = 0;
-
-       write_lock_bh(&est_lock);
-       pest = &est_list;
-       while ((est=*pest) != NULL) {
-               if (est->stats != stats) {
-                       pest = &est->next;
-                       continue;
-               }
-               *pest = est->next;
-               kfree(est);
-               killed++;
+       struct ip_vs_estimator *est = &stats->est;
+
+       spin_lock_bh(&est_lock);
+       list_del(&est->list);
+       while (list_empty(&est_list) && try_to_del_timer_sync(&est_timer) < 0) {
+               spin_unlock_bh(&est_lock);
+               cpu_relax();
+               spin_lock_bh(&est_lock);
        }
-       if (killed && est_list == NULL)
-               del_timer_sync(&est_timer);
-       write_unlock_bh(&est_lock);
+       spin_unlock_bh(&est_lock);
 }
 
 void ip_vs_zero_estimator(struct ip_vs_stats *stats)
 {
-       struct ip_vs_estimator *e;
-
-       write_lock_bh(&est_lock);
-       for (e = est_list; e; e = e->next) {
-               if (e->stats != stats)
-                       continue;
-
-               /* set counters zero */
-               e->last_conns = 0;
-               e->last_inpkts = 0;
-               e->last_outpkts = 0;
-               e->last_inbytes = 0;
-               e->last_outbytes = 0;
-               e->cps = 0;
-               e->inpps = 0;
-               e->outpps = 0;
-               e->inbps = 0;
-               e->outbps = 0;
-       }
-       write_unlock_bh(&est_lock);
+       struct ip_vs_estimator *est = &stats->est;
+
+       /* set counters zero, caller must hold the stats->lock lock */
+       est->last_inbytes = 0;
+       est->last_outbytes = 0;
+       est->last_conns = 0;
+       est->last_inpkts = 0;
+       est->last_outpkts = 0;
+       est->cps = 0;
+       est->inpps = 0;
+       est->outpps = 0;
+       est->inbps = 0;
+       est->outbps = 0;
 }
index 0efa3db4b1806cd7248cad58f5c6f8aa6a124dfd..7a6a319f544a0390b85f17a200d7360b429cc1c2 100644 (file)
@@ -539,6 +539,7 @@ static struct ip_vs_scheduler ip_vs_lblc_scheduler =
        .name =                 "lblc",
        .refcnt =               ATOMIC_INIT(0),
        .module =               THIS_MODULE,
+       .n_list =               LIST_HEAD_INIT(ip_vs_lblc_scheduler.n_list),
        .init_service =         ip_vs_lblc_init_svc,
        .done_service =         ip_vs_lblc_done_svc,
        .update_service =       ip_vs_lblc_update_svc,
@@ -550,7 +551,6 @@ static int __init ip_vs_lblc_init(void)
 {
        int ret;
 
-       INIT_LIST_HEAD(&ip_vs_lblc_scheduler.n_list);
        sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars_table);
        ret = register_ip_vs_scheduler(&ip_vs_lblc_scheduler);
        if (ret)
index 8e3bbeb4513899f3a913e4da5994d97f0c64849c..c234e73968a6314535e9e68a504069a422712327 100644 (file)
@@ -728,6 +728,7 @@ static struct ip_vs_scheduler ip_vs_lblcr_scheduler =
        .name =                 "lblcr",
        .refcnt =               ATOMIC_INIT(0),
        .module =               THIS_MODULE,
+       .n_list =               LIST_HEAD_INIT(ip_vs_lblcr_scheduler.n_list),
        .init_service =         ip_vs_lblcr_init_svc,
        .done_service =         ip_vs_lblcr_done_svc,
        .update_service =       ip_vs_lblcr_update_svc,
@@ -739,7 +740,6 @@ static int __init ip_vs_lblcr_init(void)
 {
        int ret;
 
-       INIT_LIST_HEAD(&ip_vs_lblcr_scheduler.n_list);
        sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars_table);
        ret = register_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
        if (ret)
index ac9f08e065d55e0f674bb6e129349b7829c5913d..ebcdbf75ac6583cd76312f307975c04de8409a34 100644 (file)
@@ -98,6 +98,7 @@ static struct ip_vs_scheduler ip_vs_lc_scheduler = {
        .name =                 "lc",
        .refcnt =               ATOMIC_INIT(0),
        .module =               THIS_MODULE,
+       .n_list =               LIST_HEAD_INIT(ip_vs_lc_scheduler.n_list),
        .init_service =         ip_vs_lc_init_svc,
        .done_service =         ip_vs_lc_done_svc,
        .update_service =       ip_vs_lc_update_svc,
@@ -107,7 +108,6 @@ static struct ip_vs_scheduler ip_vs_lc_scheduler = {
 
 static int __init ip_vs_lc_init(void)
 {
-       INIT_LIST_HEAD(&ip_vs_lc_scheduler.n_list);
        return register_ip_vs_scheduler(&ip_vs_lc_scheduler) ;
 }
 
index a46bf258d420f45964d5e7750e098c6a45e11c7c..92f3a6770031ed8b05cf199a6e95ab0db287115d 100644 (file)
@@ -136,6 +136,7 @@ static struct ip_vs_scheduler ip_vs_nq_scheduler =
        .name =                 "nq",
        .refcnt =               ATOMIC_INIT(0),
        .module =               THIS_MODULE,
+       .n_list =               LIST_HEAD_INIT(ip_vs_nq_scheduler.n_list),
        .init_service =         ip_vs_nq_init_svc,
        .done_service =         ip_vs_nq_done_svc,
        .update_service =       ip_vs_nq_update_svc,
@@ -145,7 +146,6 @@ static struct ip_vs_scheduler ip_vs_nq_scheduler =
 
 static int __init ip_vs_nq_init(void)
 {
-       INIT_LIST_HEAD(&ip_vs_nq_scheduler.n_list);
        return register_ip_vs_scheduler(&ip_vs_nq_scheduler);
 }
 
index 876714f23d6514135ae4401cb1561f1e00684b4e..6099a88fc2002ea68552f0713e18058bfc95af3d 100644 (file)
@@ -43,7 +43,7 @@ static struct ip_vs_protocol *ip_vs_proto_table[IP_VS_PROTO_TAB_SIZE];
 /*
  *     register an ipvs protocol
  */
-static int __used register_ip_vs_protocol(struct ip_vs_protocol *pp)
+static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp)
 {
        unsigned hash = IP_VS_PROTO_HASH(pp->protocol);
 
@@ -190,7 +190,7 @@ ip_vs_tcpudp_debug_packet(struct ip_vs_protocol *pp,
 }
 
 
-int ip_vs_protocol_init(void)
+int __init ip_vs_protocol_init(void)
 {
        char protocols[64];
 #define REGISTER_PROTOCOL(p)                   \
index c8db12d39e61b83bae055c30e50127e22090445a..358110d17e5957dd871af44faa83cfe88bbc26b4 100644 (file)
@@ -94,6 +94,7 @@ static struct ip_vs_scheduler ip_vs_rr_scheduler = {
        .name =                 "rr",                   /* name */
        .refcnt =               ATOMIC_INIT(0),
        .module =               THIS_MODULE,
+       .n_list =               LIST_HEAD_INIT(ip_vs_rr_scheduler.n_list),
        .init_service =         ip_vs_rr_init_svc,
        .done_service =         ip_vs_rr_done_svc,
        .update_service =       ip_vs_rr_update_svc,
@@ -102,7 +103,6 @@ static struct ip_vs_scheduler ip_vs_rr_scheduler = {
 
 static int __init ip_vs_rr_init(void)
 {
-       INIT_LIST_HEAD(&ip_vs_rr_scheduler.n_list);
        return register_ip_vs_scheduler(&ip_vs_rr_scheduler);
 }
 
index b64767309855f2a2efe54859ceb30d978d34ff86..a46ad9e350162b6faa59dcf0856de2a6f1313b20 100644 (file)
@@ -184,7 +184,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
 
        write_lock_bh(&__ip_vs_sched_lock);
 
-       if (scheduler->n_list.next != &scheduler->n_list) {
+       if (!list_empty(&scheduler->n_list)) {
                write_unlock_bh(&__ip_vs_sched_lock);
                ip_vs_use_count_dec();
                IP_VS_ERR("register_ip_vs_scheduler(): [%s] scheduler "
@@ -229,7 +229,7 @@ int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
        }
 
        write_lock_bh(&__ip_vs_sched_lock);
-       if (scheduler->n_list.next == &scheduler->n_list) {
+       if (list_empty(&scheduler->n_list)) {
                write_unlock_bh(&__ip_vs_sched_lock);
                IP_VS_ERR("unregister_ip_vs_scheduler(): [%s] scheduler "
                          "is not in the list. failed\n", scheduler->name);
index 2a7d31358181fea64782bda6aac11a27552f450c..77663d84cbd119e105a65e1981e0cb8e2f9c74c1 100644 (file)
@@ -138,6 +138,7 @@ static struct ip_vs_scheduler ip_vs_sed_scheduler =
        .name =                 "sed",
        .refcnt =               ATOMIC_INIT(0),
        .module =               THIS_MODULE,
+       .n_list =               LIST_HEAD_INIT(ip_vs_sed_scheduler.n_list),
        .init_service =         ip_vs_sed_init_svc,
        .done_service =         ip_vs_sed_done_svc,
        .update_service =       ip_vs_sed_update_svc,
@@ -147,7 +148,6 @@ static struct ip_vs_scheduler ip_vs_sed_scheduler =
 
 static int __init ip_vs_sed_init(void)
 {
-       INIT_LIST_HEAD(&ip_vs_sed_scheduler.n_list);
        return register_ip_vs_scheduler(&ip_vs_sed_scheduler);
 }
 
index b8fdfac650017fd5463a38aa01645bf98d1b4c24..7b979e22805647356ce0237d23ebb5c9f79ed4d4 100644 (file)
@@ -230,6 +230,7 @@ static struct ip_vs_scheduler ip_vs_sh_scheduler =
        .name =                 "sh",
        .refcnt =               ATOMIC_INIT(0),
        .module =               THIS_MODULE,
+       .n_list  =              LIST_HEAD_INIT(ip_vs_sh_scheduler.n_list),
        .init_service =         ip_vs_sh_init_svc,
        .done_service =         ip_vs_sh_done_svc,
        .update_service =       ip_vs_sh_update_svc,
@@ -239,7 +240,6 @@ static struct ip_vs_scheduler ip_vs_sh_scheduler =
 
 static int __init ip_vs_sh_init(void)
 {
-       INIT_LIST_HEAD(&ip_vs_sh_scheduler.n_list);
        return register_ip_vs_scheduler(&ip_vs_sh_scheduler);
 }
 
index 45e9bd96c286fd4bb11148c0c69522e36d5fbcd3..a652da2c3200c55e0c30e5d5c99315e95361db5f 100644 (file)
@@ -904,9 +904,9 @@ int stop_sync_thread(int state)
                 * progress of stopping the master sync daemon.
                 */
 
-               spin_lock(&ip_vs_sync_lock);
+               spin_lock_bh(&ip_vs_sync_lock);
                ip_vs_sync_state &= ~IP_VS_STATE_MASTER;
-               spin_unlock(&ip_vs_sync_lock);
+               spin_unlock_bh(&ip_vs_sync_lock);
                kthread_stop(sync_master_thread);
                sync_master_thread = NULL;
        } else if (state == IP_VS_STATE_BACKUP) {
index 772c3cb4eca18c14429f752f37b3f5de2e1b373e..9b0ef86bb1f7b03501e8f4cbab5c0be44b2b22e5 100644 (file)
@@ -126,6 +126,7 @@ static struct ip_vs_scheduler ip_vs_wlc_scheduler =
        .name =                 "wlc",
        .refcnt =               ATOMIC_INIT(0),
        .module =               THIS_MODULE,
+       .n_list =               LIST_HEAD_INIT(ip_vs_wlc_scheduler.n_list),
        .init_service =         ip_vs_wlc_init_svc,
        .done_service =         ip_vs_wlc_done_svc,
        .update_service =       ip_vs_wlc_update_svc,
@@ -135,7 +136,6 @@ static struct ip_vs_scheduler ip_vs_wlc_scheduler =
 
 static int __init ip_vs_wlc_init(void)
 {
-       INIT_LIST_HEAD(&ip_vs_wlc_scheduler.n_list);
        return register_ip_vs_scheduler(&ip_vs_wlc_scheduler);
 }
 
index 1d6932d7dc97822324e8567abf86b7d95df3a6b1..0d86a79b87b5d5c5aed7e860c38d941f626c435d 100644 (file)
@@ -212,6 +212,7 @@ static struct ip_vs_scheduler ip_vs_wrr_scheduler = {
        .name =                 "wrr",
        .refcnt =               ATOMIC_INIT(0),
        .module =               THIS_MODULE,
+       .n_list =               LIST_HEAD_INIT(ip_vs_wrr_scheduler.n_list),
        .init_service =         ip_vs_wrr_init_svc,
        .done_service =         ip_vs_wrr_done_svc,
        .update_service =       ip_vs_wrr_update_svc,
@@ -220,7 +221,6 @@ static struct ip_vs_scheduler ip_vs_wrr_scheduler = {
 
 static int __init ip_vs_wrr_init(void)
 {
-       INIT_LIST_HEAD(&ip_vs_wrr_scheduler.n_list);
        return register_ip_vs_scheduler(&ip_vs_wrr_scheduler) ;
 }
 
index 383d17359d01f1a81080df5aabef22266c1dd1c4..8e42fbbd57616316df2692a39379398f9486ac22 100644 (file)
@@ -989,7 +989,9 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
                    up->encap_rcv != NULL) {
                        int ret;
 
+                       bh_unlock_sock(sk);
                        ret = (*up->encap_rcv)(sk, skb);
+                       bh_lock_sock(sk);
                        if (ret <= 0) {
                                UDP_INC_STATS_BH(sock_net(sk),
                                                 UDP_MIB_INDATAGRAMS,
@@ -1092,7 +1094,7 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
                        if (skb1) {
                                int ret = 0;
 
-                               bh_lock_sock_nested(sk);
+                               bh_lock_sock(sk);
                                if (!sock_owned_by_user(sk))
                                        ret = udp_queue_rcv_skb(sk, skb1);
                                else
@@ -1194,7 +1196,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
 
        if (sk != NULL) {
                int ret = 0;
-               bh_lock_sock_nested(sk);
+               bh_lock_sock(sk);
                if (!sock_owned_by_user(sk))
                        ret = udp_queue_rcv_skb(sk, skb);
                else
index 5a3e87e4b18f003357720a7f79e3e6b665fb9055..41b165ffb369fec9d101c59af630860cac018d04 100644 (file)
@@ -2187,8 +2187,9 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
 #endif
                        NLA_PUT_U32(skb, RTA_IIF, iif);
        } else if (dst) {
+               struct inet6_dev *idev = ip6_dst_idev(&rt->u.dst);
                struct in6_addr saddr_buf;
-               if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev,
+               if (ipv6_dev_get_saddr(idev ? idev->dev : NULL,
                                       dst, 0, &saddr_buf) == 0)
                        NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
        }
index d1477b350f761aa474f47c7444d3327d0a19bbe1..a6aecf76a71bb05eb8a551e52217fbcaa93d6035 100644 (file)
@@ -379,7 +379,7 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
                                        uh->source, saddr, dif))) {
                struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC);
                if (buff) {
-                       bh_lock_sock_nested(sk2);
+                       bh_lock_sock(sk2);
                        if (!sock_owned_by_user(sk2))
                                udpv6_queue_rcv_skb(sk2, buff);
                        else
@@ -387,7 +387,7 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
                        bh_unlock_sock(sk2);
                }
        }
-       bh_lock_sock_nested(sk);
+       bh_lock_sock(sk);
        if (!sock_owned_by_user(sk))
                udpv6_queue_rcv_skb(sk, skb);
        else
@@ -508,7 +508,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
 
        /* deliver */
 
-       bh_lock_sock_nested(sk);
+       bh_lock_sock(sk);
        if (!sock_owned_by_user(sk))
                udpv6_queue_rcv_skb(sk, skb);
        else
index bdfb7741779441c3752176c5ad3ce585cc30cfc2..77228f28fa363240fce7da4e32d0b81bd8ea3951 100644 (file)
@@ -100,7 +100,7 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local,
 
        trans = rxrpc_get_transport(local, peer, GFP_NOIO);
        rxrpc_put_peer(peer);
-       if (!trans) {
+       if (IS_ERR(trans)) {
                _debug("no trans");
                ret = -EBUSY;
                goto error;
index 26c7e1f9a35002d3bf2dd9f825d9a54041bb96a5..9974b3f04f05cfe54142d7d55cd762021509c8e5 100644 (file)
@@ -751,7 +751,7 @@ static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
        struct nlattr *tb[TCA_ACT_MAX+1];
        struct nlattr *kind;
        struct tc_action *a = create_a(0);
-       int err = -EINVAL;
+       int err = -ENOMEM;
 
        if (a == NULL) {
                printk("tca_action_flush: couldnt create tc_action\n");
@@ -762,7 +762,7 @@ static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
        if (!skb) {
                printk("tca_action_flush: failed skb alloc\n");
                kfree(a);
-               return -ENOBUFS;
+               return err;
        }
 
        b = skb_tail_pointer(skb);
@@ -790,6 +790,8 @@ static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
        err = a->ops->walk(skb, &dcb, RTM_DELACTION, a);
        if (err < 0)
                goto nla_put_failure;
+       if (err == 0)
+               goto noflush_out;
 
        nla_nest_end(skb, nest);
 
@@ -807,6 +809,7 @@ nla_put_failure:
 nlmsg_failure:
        module_put(a->ops->owner);
 err_out:
+noflush_out:
        kfree_skb(skb);
        kfree(a);
        return err;
@@ -824,8 +827,10 @@ tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event)
                return ret;
 
        if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) {
-               if (tb[0] != NULL && tb[1] == NULL)
-                       return tca_action_flush(tb[0], n, pid);
+               if (tb[1] != NULL)
+                       return tca_action_flush(tb[1], n, pid);
+               else
+                       return -EINVAL;
        }
 
        for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
index ba1d121f312769c856821741901db6c45b276284..c25465e5607aeb32cf39fb8c784514a64ebedcbf 100644 (file)
@@ -183,6 +183,21 @@ EXPORT_SYMBOL(unregister_qdisc);
    (root qdisc, all its children, children of children etc.)
  */
 
+struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
+{
+       struct Qdisc *q;
+
+       if (!(root->flags & TCQ_F_BUILTIN) &&
+           root->handle == handle)
+               return root;
+
+       list_for_each_entry(q, &root->list, list) {
+               if (q->handle == handle)
+                       return q;
+       }
+       return NULL;
+}
+
 struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
 {
        unsigned int i;
@@ -191,16 +206,11 @@ struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
                struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
                struct Qdisc *q, *txq_root = txq->qdisc_sleeping;
 
-               if (!(txq_root->flags & TCQ_F_BUILTIN) &&
-                   txq_root->handle == handle)
-                       return txq_root;
-
-               list_for_each_entry(q, &txq_root->list, list) {
-                       if (q->handle == handle)
-                               return q;
-               }
+               q = qdisc_match_from_root(txq_root, handle);
+               if (q)
+                       return q;
        }
-       return NULL;
+       return qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle);
 }
 
 static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
@@ -321,7 +331,7 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
        if (!s || tsize != s->tsize || (!tab && tsize > 0))
                return ERR_PTR(-EINVAL);
 
-       spin_lock(&qdisc_stab_lock);
+       spin_lock_bh(&qdisc_stab_lock);
 
        list_for_each_entry(stab, &qdisc_stab_list, list) {
                if (memcmp(&stab->szopts, s, sizeof(*s)))
@@ -329,11 +339,11 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
                if (tsize > 0 && memcmp(stab->data, tab, tsize * sizeof(u16)))
                        continue;
                stab->refcnt++;
-               spin_unlock(&qdisc_stab_lock);
+               spin_unlock_bh(&qdisc_stab_lock);
                return stab;
        }
 
-       spin_unlock(&qdisc_stab_lock);
+       spin_unlock_bh(&qdisc_stab_lock);
 
        stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL);
        if (!stab)
@@ -344,9 +354,9 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
        if (tsize > 0)
                memcpy(stab->data, tab, tsize * sizeof(u16));
 
-       spin_lock(&qdisc_stab_lock);
+       spin_lock_bh(&qdisc_stab_lock);
        list_add_tail(&stab->list, &qdisc_stab_list);
-       spin_unlock(&qdisc_stab_lock);
+       spin_unlock_bh(&qdisc_stab_lock);
 
        return stab;
 }
@@ -356,14 +366,14 @@ void qdisc_put_stab(struct qdisc_size_table *tab)
        if (!tab)
                return;
 
-       spin_lock(&qdisc_stab_lock);
+       spin_lock_bh(&qdisc_stab_lock);
 
        if (--tab->refcnt == 0) {
                list_del(&tab->list);
                kfree(tab);
        }
 
-       spin_unlock(&qdisc_stab_lock);
+       spin_unlock_bh(&qdisc_stab_lock);
 }
 EXPORT_SYMBOL(qdisc_put_stab);
 
@@ -908,7 +918,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
                                        return -ENOENT;
                                q = qdisc_leaf(p, clid);
                        } else { /* ingress */
-                               q = dev->rx_queue.qdisc;
+                               q = dev->rx_queue.qdisc_sleeping;
                        }
                } else {
                        struct netdev_queue *dev_queue;
@@ -978,7 +988,7 @@ replay:
                                        return -ENOENT;
                                q = qdisc_leaf(p, clid);
                        } else { /*ingress */
-                               q = dev->rx_queue.qdisc;
+                               q = dev->rx_queue.qdisc_sleeping;
                        }
                } else {
                        struct netdev_queue *dev_queue;
@@ -1529,11 +1539,11 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
        t = 0;
 
        dev_queue = netdev_get_tx_queue(dev, 0);
-       if (tc_dump_tclass_root(dev_queue->qdisc, skb, tcm, cb, &t, s_t) < 0)
+       if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0)
                goto done;
 
        dev_queue = &dev->rx_queue;
-       if (tc_dump_tclass_root(dev_queue->qdisc, skb, tcm, cb, &t, s_t) < 0)
+       if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0)
                goto done;
 
 done:
index 7cf83b37459d0f08926baf49c07ce1ad9882b433..468574682caab154eba2d8f35b09de3f8272522e 100644 (file)
@@ -647,7 +647,7 @@ static void dev_deactivate_queue(struct net_device *dev,
        }
 }
 
-static bool some_qdisc_is_running(struct net_device *dev, int lock)
+static bool some_qdisc_is_busy(struct net_device *dev, int lock)
 {
        unsigned int i;
 
@@ -658,13 +658,14 @@ static bool some_qdisc_is_running(struct net_device *dev, int lock)
                int val;
 
                dev_queue = netdev_get_tx_queue(dev, i);
-               q = dev_queue->qdisc;
+               q = dev_queue->qdisc_sleeping;
                root_lock = qdisc_lock(q);
 
                if (lock)
                        spin_lock_bh(root_lock);
 
-               val = test_bit(__QDISC_STATE_RUNNING, &q->state);
+               val = (test_bit(__QDISC_STATE_RUNNING, &q->state) ||
+                      test_bit(__QDISC_STATE_SCHED, &q->state));
 
                if (lock)
                        spin_unlock_bh(root_lock);
@@ -689,14 +690,14 @@ void dev_deactivate(struct net_device *dev)
 
        /* Wait for outstanding qdisc_run calls. */
        do {
-               while (some_qdisc_is_running(dev, 0))
+               while (some_qdisc_is_busy(dev, 0))
                        yield();
 
                /*
                 * Double-check inside queue lock to ensure that all effects
                 * of the queue run are visible when we return.
                 */
-               running = some_qdisc_is_running(dev, 1);
+               running = some_qdisc_is_busy(dev, 1);
 
                /*
                 * The running flag should never be set at this point because
index be35422711a35aef3c3b6dfcc007557d89c168e6..6febd245e62b349b061674986a13b826cff8e02a 100644 (file)
@@ -1279,7 +1279,8 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
 
        /* delete from hash and active; remainder in destroy_class */
        qdisc_class_hash_remove(&q->clhash, &cl->common);
-       cl->parent->children--;
+       if (cl->parent)
+               cl->parent->children--;
 
        if (cl->prio_activity)
                htb_deactivate(q, cl);
index 0326d3060bc7acdea0b0f9f158f92518192a538d..0747d8a9232f4f51cf7f0950b50a1a0ae9d7d85f 100644 (file)
@@ -85,7 +85,7 @@ static struct top_srv topsrv = { 0 };
 
 static u32 htohl(u32 in, int swap)
 {
-       return swap ? (u32)___constant_swab32(in) : in;
+       return swap ? swab32(in) : in;
 }
 
 /**
index df5b3886c36b3b38d4de3f7f4f7ad8076b30e715..d98ffb75119ac02891446056b3e507c23f3453ce 100644 (file)
@@ -1277,6 +1277,7 @@ static int rtnetlink_fill_iwinfo(struct sk_buff *skb, struct net_device *dev,
        r->ifi_flags = dev_get_flags(dev);
        r->ifi_change = 0;      /* Wireless changes don't affect those flags */
 
+       NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
        /* Add the wireless events in the netlink packet */
        NLA_PUT(skb, IFLA_WIRELESS, event_len, event);
 
index 3f964db908a71466e77949568d6ea672c63f281c..ac25b4c0e982ee7d5089f7cf5c41d6d73c39ab51 100644 (file)
@@ -112,16 +112,13 @@ error_nolock:
 int xfrm_output_resume(struct sk_buff *skb, int err)
 {
        while (likely((err = xfrm_output_one(skb, err)) == 0)) {
-               struct xfrm_state *x;
-
                nf_reset(skb);
 
                err = skb->dst->ops->local_out(skb);
                if (unlikely(err != 1))
                        goto out;
 
-               x = skb->dst->xfrm;
-               if (!x)
+               if (!skb->dst->xfrm)
                        return dst_output(skb);
 
                err = nf_hook(skb->dst->ops->family,